/*
 * tqsynth.cpp -- Copyright (C) 2003 Garry Jordan
 *                A bare-bones phoneme-based voice synthesizer based on
 *                "rsynth" (C) 1994 by Nick Ing-Simmons, which utilized
 *                the Klatt synthesizer (C) 1982 by Dennis H. Klatt.
 *                Rsynth is a "public domain" text-to-speech system assembled
 *                from a variety of sources.
 *
 * I found rsynth as "rsynth-2.0.tar.gz" at:
 *                svr-ftp.eng.cam.ac.uk:/pub/comp.speech/synthesis/ 
 *
 * This file is part of DAPHNE, a laserdisc arcade game emulator
 *
 * DAPHNE is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * DAPHNE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
#ifdef _WIN32
#define _CRT_SECURE_NO_WARNINGS 1
#endif

#include <stdint.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "tqsynth.h"
#include "../io/conout.h"
#include "../io/mpo_mem.h"

#define alv 0x00000001
#define apr 0x00000002
#define bck 0x00000004
#define blb 0x00000008
#define cnt 0x00000010
#define dnt 0x00000020
#define fnt 0x00000040
#define frc 0x00000080
#define glt 0x00000100
#define hgh 0x00000200
#define lat 0x00000400
#define lbd 0x00000800
#define lbv 0x00001000
#define lmd 0x00002000
#define low 0x00004000
#define mdl 0x00008000
#define nas 0x00010000
#define pal 0x00020000
#define pla 0x00040000
#define rnd 0x00080000
#define rzd 0x00100000
#define smh 0x00200000
#define stp 0x00400000
#define umd 0x00800000
#define unr 0x01000000
#define vcd 0x02000000
#define vel 0x04000000
#define vls 0x08000000
#define vwl 0x10000000

// Variables, structs, #defines, etc. global to this module.
#define CASCADE_PARALLEL  1
#define ALL_PARALLEL      2
#define NPAR             40
#define IMPULSIVE         1
#define NATURAL           2
#define SPEED             1      // Default speed of speech.

#ifndef PI
#define PI 3.1415927
#endif

typedef struct
{
    float a;
    float b;
    float c;
    float p1;
    float p2;
} resonator_t, *resonator_ptr;

typedef struct
{
    long F0hz10;        /* Voicing fund freq in Hz          0 to 500        */        
    long AVdb;          /* Amp of voicing in dB,            0 to   70       */        
    long F1hz;          /* First formant freq in Hz,        200 to 1300     */        
    long B1hz;          /* First formant bw in Hz,          40 to 1000      */        
    long F2hz;          /* Second formant freq in Hz,       550 to 3000     */        
    long B2hz;          /* Second formant bw in Hz,         40 to 1000      */        
    long F3hz;          /* Third formant freq in Hz,        1200 to 4999    */        
    long B3hz;          /* Third formant bw in Hz,          40 to 1000      */        
    long F4hz;          /* Fourth formant freq in Hz,       1200 to 4999    */        
    long B4hz;          /* Fourth formant bw in Hz,         40 to 1000      */        
    long F5hz;          /* Fifth formant freq in Hz,        1200 to 4999    */        
    long B5hz;          /* Fifth formant bw in Hz,          40 to 1000      */        
    long F6hz;          /* Sixth formant freq in Hz,        1200 to 4999    */        
    long B6hz;          /* Sixth formant bw in Hz,          40 to 2000      */        
    long FNZhz;         /* Nasal zero freq in Hz,           248 to  528     */        
    long BNZhz;         /* Nasal zero bw in Hz,             40 to 1000      */        
    long FNPhz;         /* Nasal pole freq in Hz,           248 to  528     */        
    long BNPhz;         /* Nasal pole bw in Hz,             40 to 1000      */        
    long ASP;           /* Amp of aspiration in dB,         0 to   70       */        
    long Kopen;         /* # of samples in open period,     10 to   65      */        
    long Aturb;         /* Breathiness in voicing,          0 to   80       */        
    long TLTdb;         /* Voicing spectral tilt in dB,     0 to   24       */        
    long AF;            /* Amp of frication in dB,          0 to   80       */        
    long Kskew;         /* Skewness of alternate periods,   0 to   40 in sample#/2  */
    long A1;            /* Amp of par 1st formant in dB,    0 to   80       */        
    long B1phz;         /* Par. 1st formant bw in Hz,       40 to 1000      */        
    long A2;            /* Amp of F2 frication in dB,       0 to   80       */        
    long B2phz;         /* Par. 2nd formant bw in Hz,       40 to 1000      */        
    long A3;            /* Amp of F3 frication in dB,       0 to   80       */        
    long B3phz;         /* Par. 3rd formant bw in Hz,       40 to 1000      */        
    long A4;            /* Amp of F4 frication in dB,       0 to   80       */        
    long B4phz;         /* Par. 4th formant bw in Hz,       40 to 1000      */        
    long A5;            /* Amp of F5 frication in dB,       0 to   80       */        
    long B5phz;         /* Par. 5th formant bw in Hz,       40 to 1000      */        
    long A6;            /* Amp of F6 (same as r6pa),        0 to   80       */        
    long B6phz;         /* Par. 6th formant bw in Hz,       40 to 2000      */        
    long ANP;           /* Amp of par nasal pole in dB,     0 to   80       */        
    long AB;            /* Amp of bypass fric. in dB,       0 to   80       */        
    long AVpdb;         /* Amp of voicing,  par in dB,      0 to   70       */        
    long Gain0;         /* Overall gain, 60 dB is unity,    0 to   60       */        
} klatt_frame_t, *klatt_frame_ptr;

typedef struct 
{
    int  synthesis_model;   // CASCADE_PARALLEL | ALL_PARRALEL (default).
    int  f0_flutter;
    int  outsl;
    long samrate;           // Number of samples per second.
    long nfcascade;
    long glsource;          // NATURAL (default) | IMPULSIVE
    long nspfr;             // Number of samples per frame (10ms/frame default).
} klatt_global_t, *klatt_global_ptr;

struct trie_s
{
    struct trie_s *otherwise;
    struct trie_s *more;
    void *value;
    char ch;
};

typedef struct
{
    float v; /* boundary value */
    int t;   /* transition time */
} slope_t;

typedef struct
{
    float stdy;
    float fixd;
    char  prop;
    char  ed;
    char  id;
} interp_t, *interp_ptr;

enum Eparm_e
{
    fn, f1, f2, f3, b1, b2, b3, an, a1, a2,
    a3, a4, a5, a6, ab, av, avc, asp, af,
    nEparm
};

typedef struct Elm_s
{
    const char *name;
    char rk;
    char du;
    char ud;
    unsigned char font;
    const char  *dict;
    const char  *ipa;
    long  feat;
    interp_t p[nEparm];
} Elm_t, *Elm_ptr;

typedef struct
{
    slope_t p[nEparm];
} trans_t;

typedef struct
{
    float a;
    float b;
    float v;
} filter_t, *filter_ptr;

typedef struct trie_s *trie_ptr;

typedef struct _darray_t
{
    char     *data;          /* the items */
    unsigned items;          /* number of slots used */
    unsigned alloc;          /* number of slots allocated */
    unsigned short esize;    /* size of items */
    unsigned short get;      /* number to get */
} darray_t, *darray_ptr;

// Macros to speed things up a bit.
#define darray_init(a, sz, gt) \
    ((a)->esize = (sz), (a)->get = (gt), (a)->items = (a)->alloc = 0, (a)->data = NULL)

#define darray_find(a, n) \
    (((n) < (a)->alloc && (n) < (a)->items) \
        ? (void *) ((a)->data + (n) * (a)->esize)  \
        : Darray_find(a, n))

Elm_t Elements[] =
{
    {"END", 31, 5, 5, 0x00, NULL, NULL, 0,
        {
            {   270,    135,  50,  3,  3}, /* fn       0 */
            {   490,      0, 100,  0,  0}, /* f1       0 */
            {  1480,      0, 100,  0,  0}, /* f2       0 */
            {  2500,      0, 100,  0,  0}, /* f3       0 */
            {    60,      0, 100,  0,  0}, /* b1       0 */
            {    90,      0, 100,  0,  0}, /* b2       0 */
            {   150,      0, 100,  0,  0}, /* b3       0 */
            {   -30,  -10.5, 100,  3,  0}, /* an   -10.5 */
            {   -30,  -10.5, 100,  3,  0}, /* a1   -10.5 */
            {   -30,  -10.5, 100,  3,  0}, /* a2   -10.5 */
            {   -30,  -10.5, 100,  3,  0}, /* a3   -10.5 */
            {   -30,  -10.5, 100,  3,  0}, /* a4   -10.5 */
            {   -30,      0, 100,  3,  0}, /* a5       0 */
            {   -30,      0, 100,  3,  0}, /* a6       0 */
            {   -30,      0, 100,  3,  0}, /* ab       0 */
            {     0,      0,  50,  0,  0}, /* av       0 */
            {     0,      0,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"Q", 29, 6, 6, 0x00, NULL, NULL, 0,
        {
            {   270,    135,  50,  3,  3}, /* fn       0 */
            {   490,      0, 100,  3,  3}, /* f1       0 */
            {  1480,      0, 100,  3,  3}, /* f2       0 */
            {  2500,      0, 100,  3,  3}, /* f3       0 */
            {    60,      0, 100,  3,  3}, /* b1       0 */
            {    90,      0, 100,  3,  3}, /* b2       0 */
            {   150,      0, 100,  3,  3}, /* b3       0 */
            {   -30,  -10.5, 100,  3,  0}, /* an   -10.5 */
            {   -30,  -10.5, 100,  3,  0}, /* a1   -10.5 */
            {   -30,  -10.5, 100,  3,  0}, /* a2   -10.5 */
            {   -30,  -10.5, 100,  3,  0}, /* a3   -10.5 */
            {   -30,  -10.5, 100,  3,  0}, /* a4   -10.5 */
            {   -30,      0, 100,  3,  0}, /* a5       0 */
            {   -30,      0, 100,  3,  0}, /* a6       0 */
            {   -30,      0, 100,  3,  0}, /* ab       0 */
            {     0,      0,  50,  0,  0}, /* av       0 */
            {     0,      0,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"P", 23, 8, 8, 0x70, "p", "p", blb | stp | vls,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   190,    110,  50,  2,  2}, /* f1      15 */
            {   760,    350,  50,  2,  2}, /* f2     -30 */
            {  2500,      0, 100,  0,  2}, /* f3       0 */
            {    60,     30,  50,  2,  2}, /* b1       0 */
            {    90,     45,  50,  2,  2}, /* b2       0 */
            {   150,      0, 100,  0,  2}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            {   -30,      0, 100,  0,  0}, /* a1       0 */
            {   -30,      0, 100,  0,  0}, /* a2       0 */
            {   -30,      0, 100,  0,  0}, /* a3       0 */
            {   -30,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {     0,      0,  50,  0,  0}, /* av       0 */
            {     0,      0,  50,  0,  0}, /* avc      0 */
            {    60,     30,  50,  0,  0}, /* asp      0 */
            {    60,     30,  50,  0,  0}  /* af       0 */
        }
    },

    {"PY", 29, 1, 1, 0x70, "p", "p", blb | stp | vls,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   190,      0, 100,  0,  0}, /* f1       0 */
            {   760,      0, 100,  0,  0}, /* f2       0 */
            {  2500,      0, 100,  0,  0}, /* f3       0 */
            {    60,      0, 100,  0,  0}, /* b1       0 */
            {    90,      0, 100,  0,  0}, /* b2       0 */
            {   150,      0, 100,  0,  0}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            {  24.5,      0, 100,  0,  0}, /* a1       0 */
            {    49,      0, 100,  0,  0}, /* a2       0 */
            { 43.75,      0, 100,  0,  0}, /* a3       0 */
            {  38.5,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {     0,      0,  50,  0,  0}, /* av       0 */
            {     0,      0,  50,  0,  0}, /* avc      0 */
            {    60,     30,  50,  0,  0}, /* asp      0 */
            {    60,     30,  50,  0,  0}  /* af       0 */
        }
    },

    {"PZ", 23, 2, 2, 0x70, "p", "p", blb | stp | vls,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   190,    110,  50,  2,  2}, /* f1      15 */
            {   760,    350,  50,  2,  2}, /* f2     -30 */
            {  2500,      0, 100,  2,  2}, /* f3       0 */
            {    60,     30,  50,  2,  2}, /* b1       0 */
            {    90,     45,  50,  2,  2}, /* b2       0 */
            {   150,      0, 100,  2,  2}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            {  24.5,      0, 100,  0,  0}, /* a1       0 */
            {  38.5,      0, 100,  0,  0}, /* a2       0 */
            { 33.25,      0, 100,  0,  0}, /* a3       0 */
            {    28,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {     0,      0,  50,  0,  0}, /* av       0 */
            {     0,      0,  50,  0,  0}, /* avc      0 */
            {    60,     30,  50,  0,  0}, /* asp      0 */
            {    60,     30,  50,  0,  0}  /* af       0 */
        }
    },

    {"T", 23, 6, 6, 0x74, "t", "t", alv | stp | vls,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   190,    110,  50,  2,  2}, /* f1      15 */
            {  1780,    950,  50,  2,  2}, /* f2      60 */
            {  2680,   2680,   0,  0,  2}, /* f3       0 */
            {    60,     30,  50,  2,  2}, /* b1       0 */
            {    90,     45,  50,  2,  2}, /* b2       0 */
            {   150,    150,   0,  0,  2}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            {   -30,      0, 100,  0,  0}, /* a1       0 */
            {   -30,      0, 100,  0,  0}, /* a2       0 */
            {   -30,      0, 100,  0,  0}, /* a3       0 */
            {   -30,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {     0,      0,  50,  0,  0}, /* av       0 */
            {     0,      0,  50,  0,  0}, /* avc      0 */
            {    60,     30,  50,  0,  0}, /* asp      0 */
            {    60,     30,  50,  0,  0}  /* af       0 */
        }
    },

    {"TY", 29, 1, 1, 0x74, "t", "t", alv | stp | vls,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   190,      0, 100,  0,  0}, /* f1       0 */
            {  1780,      0, 100,  0,  0}, /* f2       0 */
            {  2680,      0, 100,  0,  0}, /* f3       0 */
            {    60,      0, 100,  0,  0}, /* b1       0 */
            {    90,      0, 100,  0,  0}, /* b2       0 */
            {   150,      0, 100,  0,  0}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            {   -30,      0, 100,  0,  0}, /* a1       0 */
            {   -30,      0, 100,  0,  0}, /* a2       0 */
            {  38.5,      0, 100,  0,  0}, /* a3       0 */
            { 50.75,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {     0,      0,  50,  0,  0}, /* av       0 */
            {     0,      0,  50,  0,  0}, /* avc      0 */
            {    60,     30,  50,  0,  0}, /* asp      0 */
            {    60,     30,  50,  0,  0}  /* af       0 */
        }
    },

    {"TZ", 23, 2, 2, 0x74, "t", "t", alv | stp | vls,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   190,    110,  50,  2,  1}, /* f1      15 */
            {  1780,    950,  50,  2,  1}, /* f2      60 */
            {  2680,   2680,   0,  2,  0}, /* f3       0 */
            {    60,     30,  50,  2,  1}, /* b1       0 */
            {    90,     45,  50,  2,  1}, /* b2       0 */
            {   150,    150,   0,  2,  0}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            {   -30,      0, 100,  0,  0}, /* a1       0 */
            {   -30,      0, 100,  0,  0}, /* a2       0 */
            {    28,      0, 100,  0,  0}, /* a3       0 */
            { 40.25,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {     0,      0,  50,  0,  0}, /* av       0 */
            {     0,      0,  50,  0,  0}, /* avc      0 */
            {    60,     30,  50,  0,  0}, /* asp      0 */
            {    60,     30,  50,  0,  0}  /* af       0 */
        }
    },

    {"K", 23, 8, 8, 0x6B, "k", "k", stp | vel | vls,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   190,    110,  50,  3,  3}, /* f1      15 */
            {  1480,   1550,  50,  3,  3}, /* f2     810 */
            {  2620,   1580,  50,  3,  3}, /* f3     270 */
            {    60,     30,  50,  3,  3}, /* b1       0 */
            {    90,     45,  50,  3,  3}, /* b2       0 */
            {   150,     75,  50,  3,  3}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            {   -30,      0, 100,  0,  0}, /* a1       0 */
            {   -30,      0, 100,  0,  0}, /* a2       0 */
            {   -30,      0, 100,  0,  0}, /* a3       0 */
            {   -30,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {     0,      0,  50,  0,  0}, /* av       0 */
            {     0,      0,  50,  0,  0}, /* avc      0 */
            {    60,     30,  50,  0,  0}, /* asp      0 */
            {    60,     30,  50,  0,  0}  /* af       0 */
        }
    },

    {"KY", 29, 1, 1, 0x6B, "k", "k", stp | vel | vls,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   190,      0, 100,  0,  0}, /* f1       0 */
            {  1480,      0, 100,  0,  0}, /* f2       0 */
            {  2620,      0, 100,  0,  0}, /* f3       0 */
            {    60,      0, 100,  0,  0}, /* b1       0 */
            {    90,      0, 100,  0,  0}, /* b2       0 */
            {   150,      0, 100,  0,  0}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            {   -30,      0, 100,  0,  0}, /* a1       0 */
            { 50.75,      0, 100,  0,  0}, /* a2       0 */
            { 50.75,      0, 100,  0,  0}, /* a3       0 */
            { 29.75,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {     0,      0,  50,  0,  0}, /* av       0 */
            {     0,      0,  50,  0,  0}, /* avc      0 */
            {    60,     30,  50,  0,  0}, /* asp      0 */
            {    60,     30,  50,  0,  0}  /* af       0 */
        }
    },

    {"KZ", 23, 4, 4, 0x6B, "k", "k", stp | vel | vls,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   190,    110,  50,  3,  3}, /* f1      15 */
            {  1480,   1550,  50,  3,  3}, /* f2     810 */
            {  2620,   1580,  50,  3,  3}, /* f3     270 */
            {    60,     30,  50,  3,  3}, /* b1       0 */
            {    90,     45,  50,  3,  3}, /* b2       0 */
            {   150,     75,  50,  3,  3}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            {   -30,      0, 100,  0,  0}, /* a1       0 */
            { 40.25,      0, 100,  0,  0}, /* a2       0 */
            { 40.25,      0, 100,  0,  0}, /* a3       0 */
            { 19.25,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {     0,      0,  50,  0,  0}, /* av       0 */
            {     0,      0,  50,  0,  0}, /* avc      0 */
            {    60,     30,  50,  0,  0}, /* asp      0 */
            {    60,     30,  50,  0,  0}  /* af       0 */
        }
    },

    {"B", 26, 12, 12, 0x62, "b", "b", blb | stp | vcd,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   190,    110,  50,  2,  2}, /* f1      15 */
            {   760,    350,  50,  2,  2}, /* f2     -30 */
            {  2500,      0, 100,  0,  2}, /* f3       0 */
            {    60,     30,  50,  2,  2}, /* b1       0 */
            {    90,     45,  50,  2,  2}, /* b2       0 */
            {   150,      0, 100,  0,  2}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            {  24.5,      0, 100,  0,  0}, /* a1       0 */
            {   -30,      0, 100,  0,  0}, /* a2       0 */
            {   -30,      0, 100,  0,  0}, /* a3       0 */
            {   -30,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    62,     31,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"BY", 29, 1, 1, 0x62, "b", "b", blb | stp | vcd,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   190,      0, 100,  0,  0}, /* f1       0 */
            {   760,      0, 100,  0,  0}, /* f2       0 */
            {  2500,      0, 100,  0,  0}, /* f3       0 */
            {    60,      0, 100,  0,  0}, /* b1       0 */
            {    90,      0, 100,  0,  0}, /* b2       0 */
            {   150,      0, 100,  0,  0}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            {  24.5,      0, 100,  0,  0}, /* a1       0 */
            {    49,      0, 100,  0,  0}, /* a2       0 */
            { 43.25,      0, 100,  0,  0}, /* a3       0 */
            {  38.5,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    62,     31,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"BZ", 26, 0, 0, 0x62, "b", "b", blb | stp | vcd,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   190,    110,  50,  2,  0}, /* f1      15 */
            {   760,    350,  50,  2,  0}, /* f2     -30 */
            {  2500,      0, 100,  0,  0}, /* f3       0 */
            {    60,     30,  50,  2,  0}, /* b1       0 */
            {    90,     45,  50,  2,  0}, /* b2       0 */
            {   150,      0, 100,  0,  0}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            {   -30,      0, 100,  0,  0}, /* a1       0 */
            {   -30,      0, 100,  0,  0}, /* a2       0 */
            {   -30,      0, 100,  0,  0}, /* a3       0 */
            {   -30,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    62,     31,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"D", 26, 8, 8, 0x64, "d", "d", alv | stp | vcd,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   190,    110,  50,  2,  2}, /* f1      15 */
            {  1780,    950,  50,  2,  2}, /* f2      60 */
            {  2680,   2680,   0,  2,  2}, /* f3       0 */
            {    60,     30,  50,  2,  2}, /* b1       0 */
            {    90,     45,  50,  2,  2}, /* b2       0 */
            {   150,    150,   0,  2,  2}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            {  31.5,      0, 100,  0,  0}, /* a1       0 */
            {   -30,      0, 100,  0,  0}, /* a2       0 */
            {   -30,      0, 100,  0,  0}, /* a3       0 */
            {   -30,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    62,     31,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"DY", 29, 1, 1, 0x64, "d", "d", alv | stp | vcd,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   190,      0, 100,  0,  0}, /* f1       0 */
            {  1780,      0, 100,  0,  0}, /* f2       0 */
            {  2680,      0, 100,  0,  0}, /* f3       0 */
            {    60,      0, 100,  0,  0}, /* b1       0 */
            {    90,      0, 100,  0,  0}, /* b2       0 */
            {   150,      0, 100,  0,  0}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            {  38.5,      0, 100,  0,  0}, /* a1       0 */
            {  38.5,      0, 100,  0,  0}, /* a2       0 */
            {    35,      0, 100,  0,  0}, /* a3       0 */
            {  45.5,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    62,     31,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"DZ", 26, 1, 1, 0x64, "d", "d", alv | stp | vcd,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   190,    110,  50,  2,  0}, /* f1      15 */
            {  1780,    950,  50,  2,  0}, /* f2      60 */
            {  2680,   2680,   0,  2,  0}, /* f3       0 */
            {    60,     30,  50,  2,  0}, /* b1       0 */
            {    90,     45,  50,  2,  0}, /* b2       0 */
            {   150,    150,   0,  2,  0}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            {  38.5,      0, 100,  0,  0}, /* a1       0 */
            {    28,      0, 100,  0,  0}, /* a2       0 */
            {  24.5,      0, 100,  0,  0}, /* a3       0 */
            {    35,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    62,     31,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"G", 26, 12, 12, 0x67, "g", "g", stp | vcd | vel,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   190,    110,  50,  3,  3}, /* f1      15 */
            {  1480,   1550,  50,  3,  3}, /* f2     810 */
            {  2620,   1580,  50,  3,  3}, /* f3     270 */
            {    60,     30,  50,  3,  3}, /* b1       0 */
            {    90,     45,  50,  3,  3}, /* b2       0 */
            {   150,     75,  50,  3,  3}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            {    35,      0, 100,  0,  0}, /* a1       0 */
            {   -30,      0, 100,  0,  0}, /* a2       0 */
            {   -30,      0, 100,  0,  0}, /* a3       0 */
            {   -30,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    62,     31,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"GY", 29, 1, 1, 0x67, "g", "g", stp | vcd | vel,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   190,      0, 100,  0,  0}, /* f1       0 */
            {  1480,      0, 100,  0,  0}, /* f2       0 */
            {  2620,      0, 100,  0,  0}, /* f3       0 */
            {    60,      0, 100,  0,  0}, /* b1       0 */
            {    90,      0, 100,  0,  0}, /* b2       0 */
            {   150,      0, 100,  0,  0}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            {    35,      0, 100,  0,  0}, /* a1       0 */
            {  45.5,      0, 100,  0,  0}, /* a2       0 */
            { 40.25,      0, 100,  0,  0}, /* a3       0 */
            {  24.5,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    62,     31,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"GZ", 26, 2, 2, 0x67, "g", "g", stp | vcd | vel,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   190,    110,  50,  3,  2}, /* f1      15 */
            {  1480,   1550,  50,  3,  2}, /* f2     810 */
            {  2620,   1580,  50,  3,  2}, /* f3     270 */
            {    60,     30,  50,  3,  2}, /* b1       0 */
            {    90,     45,  50,  3,  2}, /* b2       0 */
            {   150,     75,  50,  3,  2}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            {    35,      0, 100,  0,  0}, /* a1       0 */
            {    35,      0, 100,  0,  0}, /* a2       0 */
            { 29.75,      0, 100,  0,  0}, /* a3       0 */
            {    14,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    62,     31,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"M", 15, 8, 8, 0x6D, "m", "m", blb | nas,
        {
            {   360,    360,   0,  3,  0}, /* fn       0 */
            {   480,    480,   0,  3,  0}, /* f1       0 */
            {  1000,    350,  50,  3,  0}, /* f2    -150 */
            {  2200,      0, 100,  5,  0}, /* f3       0 */
            {    40,     20,  50,  3,  0}, /* b1       0 */
            {   175,     87,  50,  3,  0}, /* b2    -0.5 */
            {   120,      0, 100,  5,  0}, /* b3       0 */
            {    42,     21,  50,  3,  0}, /* an       0 */
            {    26,    -10, 100,  3,  0}, /* a1     -10 */
            {    30,    -10, 100,  3,  0}, /* a2     -10 */
            {    33,    -10, 100,  3,  0}, /* a3     -10 */
            {   -30,    -10, 100,  3,  0}, /* a4     -10 */
            {   -30,      0, 100,  3,  0}, /* a5       0 */
            {   -30,      0, 100,  3,  0}, /* a6       0 */
            {   -30,      0, 100,  3,  0}, /* ab       0 */
            {    62,     31,  50,  2,  0}, /* av       0 */
            {    62,     31,  50,  2,  0}, /* avc      0 */
            {     0,      0,  50,  2,  0}, /* asp      0 */
            {     0,      0,  50,  2,  0}  /* af       0 */
        }
    },

    {"N", 15, 8, 8, 0x6E, "n", "n", alv | nas,
        {
            {   450,    450,   0,  3,  0}, /* fn       0 */
            {   480,    480,   0,  3,  0}, /* f1       0 */
            {  1780,    950,  50,  3,  3}, /* f2      60 */
            {  2620,   2680,   0,  3,  0}, /* f3      60 */
            {    40,     20,  50,  3,  0}, /* b1       0 */
            {   300,    150,  50,  3,  3}, /* b2       0 */
            {   260,    130,  50,  3,  0}, /* b3       0 */
            {    42,     21,  50,  3,  0}, /* an       0 */
            {    35,    -10, 100,  3,  0}, /* a1     -10 */
            {    35,    -10, 100,  3,  0}, /* a2     -10 */
            {    35,    -10, 100,  3,  0}, /* a3     -10 */
            {    20,    -10, 100,  3,  0}, /* a4     -10 */
            {   -30,      0, 100,  3,  0}, /* a5       0 */
            {   -30,      0, 100,  3,  0}, /* a6       0 */
            {   -30,      0, 100,  3,  0}, /* ab       0 */
            {    62,     31,  50,  2,  0}, /* av       0 */
            {    62,     31,  50,  2,  0}, /* avc      0 */
            {     0,      0,  50,  2,  0}, /* asp      0 */
            {     0,      0,  50,  2,  0}  /* af       0 */
        }
    },

    {"NG", 15, 8, 8, 0x4E, "N", "N", nas | vel,
        {
            {   360,    360,   0,  3,  0}, /* fn       0 */
            {   480,    480,   0,  3,  0}, /* f1       0 */
            {   820,   1550,  50,  5,  3}, /* f2    1140 */
            {  2800,   1580,  50,  3,  3}, /* f3     180 */
            {   160,     80,   0,  5,  0}, /* b1     -80 */
            {   150,     75,  50,  5,  3}, /* b2       0 */
            {   100,     50,  50,  3,  0}, /* b3       0 */
            {    42,     21,  50,  3,  3}, /* an       0 */
            {    20,      0, 100,  3,  0}, /* a1       0 */
            {    30,      0, 100,  3,  0}, /* a2       0 */
            {    35,      0, 100,  3,  0}, /* a3       0 */
            {     0,      0, 100,  3,  0}, /* a4       0 */
            {   -30,      0, 100,  3,  0}, /* a5       0 */
            {   -30,      0, 100,  3,  0}, /* a6       0 */
            {   -30,      0, 100,  3,  0}, /* ab       0 */
            {    52,     26,  50,  2,  0}, /* av       0 */
            {    56,     28,  50,  2,  0}, /* avc      0 */
            {     0,      0,  50,  2,  0}, /* asp      0 */
            {     0,      0,  50,  2,  0}  /* af       0 */
        }
    },

    {"F", 18, 12, 12, 0x66, "f", "f", frc | lbd | vls,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   400,    170,  50,  3,  2}, /* f1     -30 */
            {  1420,    350,  50,  3,  2}, /* f2    -360 */
            {  2560,    980,  50,  3,  2}, /* f3    -300 */
            {    60,     30,  50,  3,  2}, /* b1       0 */
            {    90,     45,  50,  3,  2}, /* b2       0 */
            {   150,     75,  50,  3,  2}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            {   -30,      0, 100,  0,  0}, /* a1       0 */
            {     0,      0, 100,  0,  0}, /* a2       0 */
            {     0,      0, 100,  0,  0}, /* a3       0 */
            {   -30,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {    54,     27,  50,  0,  0}, /* ab       0 */
            {     0,      0,  50,  0,  0}, /* av       0 */
            {     0,      0,  50,  0,  0}, /* avc      0 */
            {    32,     16,  50,  0,  0}, /* asp      0 */
            {    54,     30,  50,  0,  0}  /* af       3 */
        }
    },

    {"TH", 18, 15, 15, 0x54, "T", "T", dnt | frc | vls,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   400,    170,  50,  3,  2}, /* f1     -30 */
            {  1780,   1190,  50,  3,  2}, /* f2     300 */
            {  2680,   2680,   0,  3,  2}, /* f3       0 */
            {    60,     30,  50,  3,  2}, /* b1       0 */
            {    90,     45,  50,  3,  2}, /* b2       0 */
            {   150,    150,   0,  3,  2}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            {   -30,      0, 100,  0,  0}, /* a1       0 */
            { 26.25,      0, 100,  0,  0}, /* a2       0 */
            {    28,      0, 100,  0,  0}, /* a3       0 */
            { 22.75,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {     0,      0,  50,  0,  0}, /* av       0 */
            {     0,      0,  50,  0,  0}, /* avc      0 */
            {    60,     30,  50,  0,  0}, /* asp      0 */
            {    60,     30,  50,  0,  0}  /* af       0 */
        }
    },

    {"S", 18, 12, 12, 0x73, "s", "s", alv | frc | vls,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   400,    170,  50,  3,  2}, /* f1     -30 */
            {  1720,    950,  50,  3,  2}, /* f2      90 */
            {  2620,      0, 100,  3,  2}, /* f3       0 */
            {   200,    100,  50,  3,  2}, /* b1       0 */
            {    96,     48,  50,  3,  2}, /* b2       0 */
            {   220,      0, 100,  3,  2}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            {   -30,      0, 100,  0,  0}, /* a1       0 */
            {    28,      0, 100,  0,  0}, /* a2       0 */
            {    28,      0, 100,  0,  0}, /* a3       0 */
            { 40.25,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {     0,      0,  50,  0,  0}, /* av       0 */
            {     0,      0,  50,  0,  0}, /* avc      0 */
            {    32,     16,  50,  0,  0}, /* asp      0 */
            {    60,     30,  50,  0,  0}  /* af       0 */
        }
    },

    {"SH", 18, 12, 12, 0x53, "S", "S", frc | pla | vls,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   400,    170,  50,  3,  2}, /* f1     -30 */
            {  2200,   1190,  50,  3,  2}, /* f2      90 */
            {  2560,      0, 100,  3,  2}, /* f3       0 */
            {    60,     30,  50,  3,  2}, /* b1       0 */
            {    90,     45,  50,  3,  2}, /* b2       0 */
            {   150,      0, 100,  3,  2}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            {   -30,      0, 100,  0,  0}, /* a1       0 */
            {  31.5,      0, 100,  0,  0}, /* a2       0 */
            {    42,      0, 100,  0,  0}, /* a3       0 */
            {  31.5,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {     0,      0,  50,  0,  0}, /* av       0 */
            {     0,      0,  50,  0,  0}, /* avc      0 */
            {    60,     30,  50,  0,  0}, /* asp      0 */
            {    60,     30,  50,  0,  0}  /* af       0 */
        }
    },

    {"X", 18, 12, 12, 0x78, "x", "x", frc | vel | vls,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   190,    110,  50,  3,  3}, /* f1      15 */
            {  1480,   1550,  50,  3,  3}, /* f2     810 */
            {  2620,   1580,  50,  3,  3}, /* f3     270 */
            {    60,     30,  50,  3,  3}, /* b1       0 */
            {    90,     45,  50,  3,  3}, /* b2       0 */
            {   150,     75,  50,  3,  3}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            {   -30,      0, 100,  0,  0}, /* a1       0 */
            { 40.25,      0, 100,  0,  0}, /* a2       0 */
            { 40.25,      0, 100,  0,  0}, /* a3       0 */
            { 19.25,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {     0,      0,  50,  0,  0}, /* av       0 */
            {     0,      0,  50,  0,  0}, /* avc      0 */
            {    60,     30,  50,  0,  0}, /* asp      0 */
            {    60,     30,  50,  0,  0}  /* af       0 */
        }
    },

    {"H", 9, 10, 10, 0x68, "h", "h", apr | glt,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   490,      0, 100,  0,  7}, /* f1       0 */
            {  1480,      0, 100,  0,  7}, /* f2       0 */
            {  2500,      0, 100,  0,  7}, /* f3       0 */
            {    60,      0, 100,  0,  7}, /* b1       0 */
            {    90,      0, 100,  0,  7}, /* b2       0 */
            {   150,      0, 100,  0,  7}, /* b3       0 */
            {   -30,      0, 100,  0,  7}, /* an       0 */
            {    35,    -14, 100,  0,  7}, /* a1     -14 */
            { 36.75,    -14, 100,  0,  7}, /* a2     -14 */
            { 26.25,     -7, 100,  0,  7}, /* a3      -7 */
            { 22.75,   -3.5, 100,  0,  7}, /* a4    -3.5 */
            {   -30,      0, 100,  0,  7}, /* a5       0 */
            {   -30,      0, 100,  0,  7}, /* a6       0 */
            {   -30,      0, 100,  0,  7}, /* ab       0 */
            {     0,      0,  50,  0,  0}, /* av       0 */
            {     0,      0,  50,  0,  0}, /* avc      0 */
            {    60,     30,  50,  0,  0}, /* asp      0 */
            {    60,     30,  50,  0,  0}  /* af       0 */
        }
    },

    {"V", 20, 4, 4, 0x76, "v", "v", frc | lbd | vcd,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   280,    170,  50,  3,  2}, /* f1      30 */
            {  1420,    350,  50,  3,  2}, /* f2    -360 */
            {  2560,    980,  50,  3,  2}, /* f3    -300 */
            {    60,     30,  50,  3,  2}, /* b1       0 */
            {    90,     45,  50,  3,  2}, /* b2       0 */
            {   150,     75,  50,  3,  2}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            { 29.75,      0, 100,  0,  0}, /* a1       0 */
            { 40.25,      0, 100,  0,  0}, /* a2       0 */
            { 36.75,      0, 100,  0,  0}, /* a3       0 */
            { 33.25,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    62,     31,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"QQ", 30, 0, 0, 0x5A, "Z", "Z", frc | vcd,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   280,      0, 100,  0,  0}, /* f1       0 */
            {  1420,      0, 100,  0,  0}, /* f2       0 */
            {  2560,      0, 100,  0,  0}, /* f3       0 */
            {    60,      0, 100,  0,  0}, /* b1       0 */
            {    90,      0, 100,  0,  0}, /* b2       0 */
            {   150,      0, 100,  0,  0}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            { 29.75,      0, 100,  0,  0}, /* a1       0 */
            { 40.25,      0, 100,  0,  0}, /* a2       0 */
            { 36.75,      0, 100,  0,  0}, /* a3       0 */
            { 33.25,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    62,     31,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"DH", 20, 4, 4, 0x54, "D", "D", dnt | frc | vcd,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   280,    170,  50,  3,  2}, /* f1      30 */
            {  1600,   1190,  50,  3,  2}, /* f2     390 */
            {  2560,      0, 100,  3,  2}, /* f3       0 */
            {    60,     30,  50,  3,  2}, /* b1       0 */
            {    90,     45,  50,  3,  2}, /* b2       0 */
            {   150,      0, 100,  3,  2}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            { 29.75,      0, 100,  0,  0}, /* a1       0 */
            {  31.5,      0, 100,  0,  0}, /* a2       0 */
            { 26.25,      0, 100,  0,  0}, /* a3       0 */
            {    28,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {    54,     27,  50,  0,  0}, /* ab       0 */
            {    36,     18,  50,  0,  0}, /* av       0 */
            {    54,     27,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {    60,     30,  50,  0,  0}  /* af       0 */
        }
    },

    {"DI", 20, 4, 4, 0x54, "D", "D", dnt | frc | vcd,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   280,    170,  50,  3,  2}, /* f1      30 */
            {  1600,   1190,  50,  3,  2}, /* f2     390 */
            {  2560,      0, 100,  3,  2}, /* f3       0 */
            {    60,     30,  50,  3,  2}, /* b1       0 */
            {    90,     45,  50,  3,  2}, /* b2       0 */
            {   150,      0, 100,  3,  2}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            { 29.75,      0, 100,  0,  0}, /* a1       0 */
            {  31.5,      0, 100,  0,  0}, /* a2       0 */
            { 26.25,      0, 100,  0,  0}, /* a3       0 */
            {    28,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    62,     31,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"Z", 20, 4, 4, 0x7A, "z", "z", alv | frc | vcd,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   280,    170,  50,  3,  2}, /* f1      30 */
            {  1720,    950,  50,  3,  2}, /* f2      90 */
            {  2560,      0, 100,  3,  2}, /* f3       0 */
            {    60,     30,  50,  3,  2}, /* b1       0 */
            {    90,     45,  50,  3,  2}, /* b2       0 */
            {   150,      0, 100,  3,  2}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            { 29.75,      0, 100,  0,  0}, /* a1       0 */
            {  24.5,      0, 100,  0,  0}, /* a2       0 */
            {  24.5,      0, 100,  0,  0}, /* a3       0 */
            { 36.75,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {    40,     20,  50,  0,  0}, /* av       0 */
            {    54,     27,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {    60,     30,  50,  0,  0}  /* af       0 */
        }
    },

    {"ZZ", 20, 4, 4, 0x7A, "z", "z", alv | frc | vcd,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   280,    170,  50,  3,  2}, /* f1      30 */
            {  1720,    950,  50,  3,  2}, /* f2      90 */
            {  2560,      0, 100,  3,  2}, /* f3       0 */
            {    60,     30,  50,  3,  2}, /* b1       0 */
            {    90,     45,  50,  3,  2}, /* b2       0 */
            {   150,      0, 100,  3,  2}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            { 29.75,      0, 100,  0,  0}, /* a1       0 */
            {  24.5,      0, 100,  0,  0}, /* a2       0 */
            {  24.5,      0, 100,  0,  0}, /* a3       0 */
            { 36.75,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    62,     31,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"ZH", 20, 4, 4, 0x5A, "Z", "Z", frc | pla | vcd,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   280,    170,  50,  3,  2}, /* f1      30 */
            {  2020,   1190,  50,  3,  2}, /* f2     180 */
            {  2560,      0, 100,  3,  2}, /* f3       0 */
            {    60,     30,  50,  3,  2}, /* b1       0 */
            {    90,     45,  50,  3,  2}, /* b2       0 */
            {   150,      0, 100,  3,  2}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            { 29.75,      0, 100,  0,  0}, /* a1       0 */
            { 26.25,      0, 100,  0,  0}, /* a2       0 */
            { 36.75,      0, 100,  0,  0}, /* a3       0 */
            { 26.25,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    62,     31,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"CH", 23, 4, 4, 0x74, "t", "t", alv | stp | vls,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   190,    110,  50,  2,  2}, /* f1      15 */
            {  1780,    950,  50,  2,  2}, /* f2      60 */
            {  2680,   2680,   0,  2,  2}, /* f3       0 */
            {    60,     30,  50,  2,  2}, /* b1       0 */
            {    90,     45,  50,  2,  2}, /* b2       0 */
            {   150,    150,   0,  2,  2}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            {   -30,      0, 100,  0,  0}, /* a1       0 */
            {   -30,      0, 100,  0,  0}, /* a2       0 */
            {   -30,      0, 100,  0,  0}, /* a3       0 */
            {   -30,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {     0,      0,  50,  0,  0}, /* av       0 */
            {     0,      0,  50,  0,  0}, /* avc      0 */
            {    60,     30,  50,  0,  0}, /* asp      0 */
            {    60,     30,  50,  0,  0}  /* af       0 */
        }
    },

    {"CI", 18, 8, 8, 0x53, "S", "S", frc | pla | vls,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   400,    170,  50,  3,  2}, /* f1     -30 */
            {  2020,   1190,  50,  3,  2}, /* f2     180 */
            {  2560,      0, 100,  3,  2}, /* f3       0 */
            {    60,     30,  50,  3,  2}, /* b1       0 */
            {    90,     45,  50,  3,  2}, /* b2       0 */
            {   150,      0, 100,  3,  2}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            {   -30,      0, 100,  0,  0}, /* a1       0 */
            {  31.5,      0, 100,  0,  0}, /* a2       0 */
            {    42,      0, 100,  0,  0}, /* a3       0 */
            {  31.5,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {     0,      0,  50,  0,  0}, /* av       0 */
            {     0,      0,  50,  0,  0}, /* avc      0 */
            {    60,     30,  50,  0,  0}, /* asp      0 */
            {    60,     30,  50,  0,  0}  /* af       0 */
        }
    },

    {"J", 26, 4, 4, 0x64, "d", "d", alv | stp | vcd,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   190,    110,  50,  2,  2}, /* f1      15 */
            {  1780,    950,  50,  2,  2}, /* f2      60 */
            {  2680,   2680,   0,  2,  2}, /* f3       0 */
            {    60,     30,  50,  2,  2}, /* b1       0 */
            {    90,     45,  50,  2,  2}, /* b2       0 */
            {   150,    150,   0,  2,  2}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            {  31.5,      0, 100,  0,  0}, /* a1       0 */
            {   -30,      0, 100,  0,  0}, /* a2       0 */
            {   -30,      0, 100,  0,  0}, /* a3       0 */
            {   -30,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    62,     31,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"JY", 20, 3, 3, 0x5A, "Z", "Z", frc | pla | vcd,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   280,    170,  50,  3,  2}, /* f1      30 */
            {  2020,   1190,  50,  3,  2}, /* f2     180 */
            {  2560,      0, 100,  3,  2}, /* f3       0 */
            {    60,     30,  50,  3,  2}, /* b1       0 */
            {    90,     45,  50,  3,  2}, /* b2       0 */
            {   150,      0, 100,  3,  2}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            { 29.75,      0, 100,  0,  0}, /* a1       0 */
            { 26.25,      0, 100,  0,  0}, /* a2       0 */
            { 36.75,      0, 100,  0,  0}, /* a3       0 */
            { 26.25,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    62,     31,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"L", 11, 8, 8, 0x6C, "l", "l", alv | lat | vcd,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   460,    230,  50,  6,  0}, /* f1       0 */
            {  1480,    710,  50,  6,  0}, /* f2     -30 */
            {  2500,   1220,  50,  6,  0}, /* f3     -30 */
            {    60,     30,  50,  6,  0}, /* b1       0 */
            {    90,     45,  50,  6,  0}, /* b2       0 */
            {   150,     75,  50,  6,  0}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            { 36.75,      0, 100,  0,  0}, /* a1       0 */
            { 26.25,      0, 100,  0,  0}, /* a2       0 */
            { 26.25,      0, 100,  0,  0}, /* a3       0 */
            {    21,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    62,     31,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"LL", 11, 8, 8, 0x6C, "l", "l", alv | lat | vcd,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   460,    230,  50,  6,  0}, /* f1       0 */
            {   940,    470,  50,  6,  0}, /* f2       0 */
            {  2500,   1220,  50,  6,  0}, /* f3     -30 */
            {    60,     30,  50,  6,  0}, /* b1       0 */
            {    90,     45,  50,  6,  0}, /* b2       0 */
            {   150,     75,  50,  6,  0}, /* b3       0 */
            {   -30,      0, 100,  0,  0}, /* an       0 */
            { 36.75,      0, 100,  0,  0}, /* a1       0 */
            { 26.25,      0, 100,  0,  0}, /* a2       0 */
            { 26.25,      0, 100,  0,  0}, /* a3       0 */
            {    21,      0, 100,  0,  0}, /* a4       0 */
            {   -30,      0, 100,  0,  0}, /* a5       0 */
            {   -30,      0, 100,  0,  0}, /* a6       0 */
            {   -30,      0, 100,  0,  0}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    62,     31,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"RX", 10, 10, 10, 0xD5, "R", "<rzd>", rzd,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   490,      0, 100,  0,  5}, /* f1       0 */
            {  1180,      0, 100,  0,  5}, /* f2       0 */
            {  1600,   1600,   0,  5,  5}, /* f3       0 */
            {    60,     30,  50,  0,  5}, /* b1       0 */
            {    90,     45,  50,  5,  5}, /* b2       0 */
            {    70,     35,  50,  5,  5}, /* b3       0 */
            {   -30,      0, 100,  5,  5}, /* an       0 */
            {    42,     21,  50,  5,  5}, /* a1       0 */
            {    35,   17.5,  50,  5,  5}, /* a2       0 */
            {    35,   17.5,  50,  5,  5}, /* a3       0 */
            {   -30,      0,  50,  5,  5}, /* a4      15 */
            {   -30,    -15,  50,  5,  5}, /* a5       0 */
            {   -30,    -15,  50,  5,  5}, /* a6       0 */
            {   -30,    -15,  50,  5,  5}, /* ab       0 */
            {    50,     25,  50,  0,  0}, /* av       0 */
            {    16,      8,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"R", 10, 11, 11, 0xA8, "r", "r", alv | apr,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   490,      0, 100,  0,  5}, /* f1       0 */
            {  1180,    590,  50,  5,  5}, /* f2       0 */
            {  1600,    740,  50,  5,  5}, /* f3     -60 */
            {    60,      0, 100,  0,  5}, /* b1       0 */
            {    90,     45,  50,  5,  5}, /* b2       0 */
            {   150,     75,  50,  5,  5}, /* b3       0 */
            {   -30,      0, 100,  5,  5}, /* an       0 */
            {    42,     21,  50,  5,  5}, /* a1       0 */
            {    35,   17.5,  50,  5,  5}, /* a2       0 */
            {    35,   17.5,  50,  5,  5}, /* a3       0 */
            {   -30,      0,  50,  5,  5}, /* a4      15 */
            {   -30,    -15,  50,  5,  5}, /* a5       0 */
            {   -30,    -15,  50,  5,  5}, /* a6       0 */
            {   -30,    -15,  50,  5,  5}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    62,     31,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"W", 10, 8, 8, 0x77, "w", "w", apr | lbv | vcd,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   190,     50,  50,  4,  4}, /* f1     -45 */
            {   760,    350,  50,  4,  4}, /* f2     -30 */
            {  2020,    980,  50,  4,  4}, /* f3     -30 */
            {    60,     30,  50,  4,  4}, /* b1       0 */
            {    90,     45,  50,  4,  4}, /* b2       0 */
            {   150,     75,  50,  4,  4}, /* b3       0 */
            {   -30,      0, 100,  4,  4}, /* an       0 */
            { 43.75,     21,  50,  4,  4}, /* a1  -0.875 */
            {    28,     14,  50,  4,  4}, /* a2       0 */
            {    21,   10.5,  50,  4,  4}, /* a3       0 */
            {   -30,      0,  50,  4,  4}, /* a4      15 */
            {   -30,    -15,  50,  4,  4}, /* a5       0 */
            {   -30,    -15,  50,  4,  4}, /* a6       0 */
            {   -30,    -15,  50,  4,  4}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    62,     31,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"Y", 10, 7, 7, 0x6A, "j", "j", apr | pal | vcd,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   250,    110,  50,  4,  4}, /* f1     -15 */
            {  2500,   1190,  50,  4,  4}, /* f2     -60 */
            {  2980,   1460,  50,  4,  4}, /* f3     -30 */
            {    60,     30,  50,  4,  4}, /* b1       0 */
            {    90,     45,  50,  4,  4}, /* b2       0 */
            {   150,     75,  50,  4,  4}, /* b3       0 */
            {   -30,      0, 100,  4,  4}, /* an       0 */
            { 50.75,   24.5,  50,  4,  4}, /* a1  -0.875 */
            { 33.25,   17.5,  50,  4,  4}, /* a2   0.875 */
            {  38.5,   17.5,  50,  4,  4}, /* a3   -1.75 */
            {  31.5,     14,  50,  4,  4}, /* a4   -1.75 */
            {   -30,    -15,  50,  4,  4}, /* a5       0 */
            {   -30,    -15,  50,  4,  4}, /* a6       0 */
            {   -30,    -15,  50,  4,  4}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    16,      8,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"I", 2, 8, 6, 0x49, "I", "I", fnt | smh | unr | vwl,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   400,    170,  50,  4,  4}, /* f1     -30 */
            {  2080,   1070,  50,  4,  4}, /* f2      30 */
            {  2560,   1340,  50,  4,  4}, /* f3      60 */
            {    60,     30,  50,  4,  4}, /* b1       0 */
            {    90,     45,  50,  4,  4}, /* b2       0 */
            {   150,     75,  50,  4,  4}, /* b3       0 */
            {   -30,      0, 100,  4,  4}, /* an       0 */
            { 50.75,   24.5,  50,  4,  4}, /* a1  -0.875 */
            { 36.75,   17.5,  50,  4,  4}, /* a2  -0.875 */
            {    35,   17.5,  50,  4,  4}, /* a3       0 */
            { 29.75,     14,  50,  4,  4}, /* a4  -0.875 */
            {   -30,    -15,  50,  4,  4}, /* a5       0 */
            {   -30,    -15,  50,  4,  4}, /* a6       0 */
            {   -30,    -15,  50,  4,  4}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    16,      8,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"E", 2, 8, 4, 0x45, "e", "E", fnt | lmd | unr | vwl,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   640,    350,  50,  4,  4}, /* f1      30 */
            {  2020,   1070,  50,  4,  4}, /* f2      60 */
            {  2500,   1220,  50,  4,  4}, /* f3     -30 */
            {    60,     30,  50,  4,  4}, /* b1       0 */
            {    90,     45,  50,  4,  4}, /* b2       0 */
            {   150,     75,  50,  4,  4}, /* b3       0 */
            {   -30,      0, 100,  4,  4}, /* an       0 */
            { 50.75,   24.5,  50,  4,  4}, /* a1  -0.875 */
            {    42,     21,  50,  4,  4}, /* a2       0 */
            {  38.5,   17.5,  50,  4,  4}, /* a3   -1.75 */
            {  31.5,     14,  50,  4,  4}, /* a4   -1.75 */
            {   -30,    -15,  50,  4,  4}, /* a5       0 */
            {   -30,    -15,  50,  4,  4}, /* a6       0 */
            {   -30,    -15,  50,  4,  4}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    16,      8,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"AA", 2, 10, 5, 0x51, "&", "&", fnt | low |unr | vwl,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   790,    410,  50,  4,  4}, /* f1      15 */
            {  1780,    950,  50,  4,  4}, /* f2      60 */
            {  2500,   1220,  50,  4,  4}, /* f3     -30 */
            {   130,     65,  50,  4,  4}, /* b1       0 */
            {    90,     45,  50,  4,  4}, /* b2       0 */
            {   150,     75,  50,  4,  4}, /* b3       0 */
            {   -30,      0, 100,  4,  4}, /* an       0 */
            { 50.75,   24.5,  50,  4,  4}, /* a1  -0.875 */
            { 47.25,   24.5,  50,  4,  4}, /* a2   0.875 */
            {  38.5,   17.5,  50,  4,  4}, /* a3   -1.75 */
            {  31.5,     14,  50,  4,  4}, /* a4   -1.75 */
            {   -30,    -15,  50,  4,  4}, /* a5       0 */
            {   -30,    -15,  50,  4,  4}, /* a6       0 */
            {   -30,    -15,  50,  4,  4}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    16,      8,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"U", 2, 9, 6, 0xC3, "V", "V", bck | lmd | unr | vwl,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   700,    350,  50,  4,  4}, /* f1       0 */
            {  1360,    710,  50,  4,  4}, /* f2      30 */
            {  2500,   1220,  50,  4,  4}, /* f3     -30 */
            {    60,     30,  50,  4,  4}, /* b1       0 */
            {    90,     45,  50,  4,  4}, /* b2       0 */
            {   150,     75,  50,  4,  4}, /* b3       0 */
            {   -30,      0, 100,  4,  4}, /* an       0 */
            { 50.75,   24.5,  50,  4,  4}, /* a1  -0.875 */
            { 43.75,     21,  50,  4,  4}, /* a2  -0.875 */
            {  31.5,     14,  50,  4,  4}, /* a3   -1.75 */
            {  24.5,   10.5,  50,  4,  4}, /* a4   -1.75 */
            {   -30,    -15,  50,  4,  4}, /* a5       0 */
            {   -30,    -15,  50,  4,  4}, /* a6       0 */
            {   -30,    -15,  50,  4,  4}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    16,      8,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"O", 2, 9, 6, 0x81, "0", "A.", bck | low | rnd | vwl,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   610,    290,  50,  4,  4}, /* f1     -15 */
            {   880,    470,  50,  4,  4}, /* f2      30 */
            {  2500,   1220,  50,  4,  4}, /* f3     -30 */
            {    60,     30,  50,  4,  4}, /* b1       0 */
            {    90,     45,  50,  4,  4}, /* b2       0 */
            {   150,     75,  50,  4,  4}, /* b3       0 */
            {   -30,      0, 100,  4,  4}, /* an       0 */
            { 50.75,   24.5,  50,  4,  4}, /* a1  -0.875 */
            { 47.25,   24.5,  50,  4,  4}, /* a2   0.875 */
            { 22.75,   10.5,  50,  4,  4}, /* a3  -0.875 */
            { 15.75,      7,  50,  4,  4}, /* a4  -0.875 */
            {   -30,    -15,  50,  4,  4}, /* a5       0 */
            {   -30,    -15,  50,  4,  4}, /* a6       0 */
            {   -30,    -15,  50,  4,  4}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    16,      8,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"OO", 2, 6, 4, 0x55, "U", "U", bck | rnd | smh | vwl,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   370,    170,  50,  4,  4}, /* f1     -15 */
            {  1000,    470,  50,  4,  4}, /* f2     -30 */
            {  2500,   1220,  50,  4,  4}, /* f3     -30 */
            {    60,     30,  50,  4,  4}, /* b1       0 */
            {    90,     45,  50,  4,  4}, /* b2       0 */
            {   150,     75,  50,  4,  4}, /* b3       0 */
            {   -30,      0, 100,  4,  4}, /* an       0 */
            { 50.75,   24.5,  50,  4,  4}, /* a1  -0.875 */
            {    42,     21,  50,  4,  4}, /* a2       0 */
            {    28,     14,  50,  4,  4}, /* a3       0 */
            { 22.75,   10.5,  50,  4,  4}, /* a4  -0.875 */
            {   -30,    -15,  50,  4,  4}, /* a5       0 */
            {   -30,    -15,  50,  4,  4}, /* a6       0 */
            {   -30,    -15,  50,  4,  4}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    16,      8,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"A", 2, 4, 4, 0xAB, "@", "@", cnt | mdl | unr | vwl,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   490,    230,  50,  4,  4}, /* f1     -15 */
            {  1480,    710,  50,  4,  4}, /* f2     -30 */
            {  2500,   1220,  50,  4,  4}, /* f3     -30 */
            {    60,     30,  50,  4,  4}, /* b1       0 */
            {    90,     45,  50,  4,  4}, /* b2       0 */
            {   150,     75,  50,  4,  4}, /* b3       0 */
            {   -30,      0, 100,  4,  4}, /* an       0 */
            { 50.75,   24.5,  50,  4,  4}, /* a1  -0.875 */
            { 50.75,   24.5,  50,  4,  4}, /* a2  -0.875 */
            { 33.25,   17.5,  50,  4,  4}, /* a3   0.875 */
            { 26.25,     14,  50,  4,  4}, /* a4   0.875 */
            {   -30,    -15,  50,  4,  4}, /* a5       0 */
            {   -30,    -15,  50,  4,  4}, /* a6       0 */
            {   -30,    -15,  50,  4,  4}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    16,      8,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"EE", 2, 11, 7, 0x69, "i", "i", fnt | hgh | unr | vwl,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   250,    110,  50,  4,  4}, /* f1     -15 */
            {  2320,   1190,  50,  4,  4}, /* f2      30 */
            {  3200,   1580,  50,  4,  4}, /* f3     -20 */
            {    60,     30,  50,  4,  4}, /* b1       0 */
            {    90,     45,  50,  4,  4}, /* b2       0 */
            {   150,     75,  50,  4,  4}, /* b3       0 */
            {   -30,      0, 100,  4,  4}, /* an       0 */
            { 50.75,   24.5,  50,  4,  4}, /* a1  -0.875 */
            { 33.25,   17.5,  50,  4,  4}, /* a2   0.875 */
            { 36.75,   17.5,  50,  4,  4}, /* a3  -0.875 */
            {  31.5,     14,  50,  4,  4}, /* a4   -1.75 */
            {   -30,    -15,  50,  4,  4}, /* a5       0 */
            {   -30,    -15,  50,  4,  4}, /* a6       0 */
            {   -30,    -15,  50,  4,  4}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    16,      8,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"ER", 2, 16, 16, 0xCE, "3", "V\"", cnt | lmd | unr | vwl,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   580,    290,  50,  4,  4}, /* f1       0 */
            {  1420,    710,  50,  4,  4}, /* f2       0 */
            {  2500,   1220,  50,  4,  4}, /* f3     -30 */
            {    60,     30,  50,  4,  4}, /* b1       0 */
            {    90,     45,  50,  4,  4}, /* b2       0 */
            {   150,     75,  50,  4,  4}, /* b3       0 */
            {   -30,      0, 100,  4,  4}, /* an       0 */
            { 50.75,   24.5,  50,  4,  4}, /* a1  -0.875 */
            {  45.5,     21,  50,  4,  4}, /* a2   -1.75 */
            { 33.25,   17.5,  50,  4,  4}, /* a3   0.875 */
            { 26.25,     14,  50,  4,  4}, /* a4   0.875 */
            {   -30,    -15,  50,  4,  4}, /* a5       0 */
            {   -30,    -15,  50,  4,  4}, /* a6       0 */
            {   -30,    -15,  50,  4,  4}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    16,      8,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"AR", 2, 15, 15, 0x41, "A", "A", bck | low | unr | vwl,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   790,    410,  50,  4,  4}, /* f1      15 */
            {   880,    470,  50,  4,  4}, /* f2      30 */
            {  2500,   1220,  50,  4,  4}, /* f3     -30 */
            {    60,     30,  50,  4,  4}, /* b1       0 */
            {    90,     45,  50,  4,  4}, /* b2       0 */
            {   150,     75,  50,  4,  4}, /* b3       0 */
            {   -30,      0, 100,  4,  4}, /* an       0 */
            { 50.75,   24.5,  50,  4,  4}, /* a1  -0.875 */
            {    49,   24.5,  50,  4,  4}, /* a2       0 */
            { 29.75,     14,  50,  4,  4}, /* a3  -0.875 */
            { 22.75,   10.5,  50,  4,  4}, /* a4  -0.875 */
            {   -30,    -15,  50,  4,  4}, /* a5       0 */
            {   -30,    -15,  50,  4,  4}, /* a6       0 */
            {   -30,    -15,  50,  4,  4}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    16,      8,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"AW", 2, 16, 10, 0x8D, "O", "O", bck | lmd | rnd | vwl,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   490,    230,  50,  4,  4}, /* f1     -15 */
            {   820,    470,  50,  4,  4}, /* f2      60 */
            {  2500,   1220,  50,  4,  4}, /* f3     -30 */
            {    60,     30,  50,  4,  4}, /* b1       0 */
            {    90,     45,  50,  4,  4}, /* b2       0 */
            {   150,     75,  50,  4,  4}, /* b3       0 */
            {   -30,      0, 100,  4,  4}, /* an       0 */
            { 50.75,   24.5,  50,  4,  4}, /* a1  -0.875 */
            {  45.5,     21,  50,  4,  4}, /* a2   -1.75 */
            { 22.75,   10.5,  50,  4,  4}, /* a3  -0.875 */
            {  17.5,      7,  50,  4,  4}, /* a4   -1.75 */
            {   -30,    -15,  50,  4,  4}, /* a5       0 */
            {   -30,    -15,  50,  4,  4}, /* a6       0 */
            {   -30,    -15,  50,  4,  4}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    16,      8,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"UU", 2, 14, 9, 0x75, "u", "u", bck | hgh | rnd | vwl,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   250,    110,  50,  4,  4}, /* f1     -15 */
            {   880,    470,  50,  4,  4}, /* f2      30 */
            {  2200,   1100,  50,  4,  4}, /* f3       0 */
            {    60,     30,  50,  4,  4}, /* b1       0 */
            {    90,     45,  50,  4,  4}, /* b2       0 */
            {   150,     75,  50,  4,  4}, /* b3       0 */
            {   -30,      0, 100,  4,  4}, /* an       0 */
            { 50.75,   24.5,  50,  4,  4}, /* a1  -0.875 */
            {  38.5,   17.5,  50,  4,  4}, /* a2   -1.75 */
            {  17.5,      7,  50,  4,  4}, /* a3   -1.75 */
            {  10.5,    3.5,  50,  4,  4}, /* a4   -1.75 */
            {   -30,    -15,  50,  4,  4}, /* a5       0 */
            {   -30,    -15,  50,  4,  4}, /* a6       0 */
            {   -30,    -15,  50,  4,  4}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    16,      8,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"AI", 2, 9, 6, 0x45, "e", "E", fnt | lmd | unr | vwl,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   640,    290,  50,  5,  5}, /* f1     -30 */
            {  1600,    830,  50,  5,  5}, /* f2      30 */
            {  2500,   1220,  50,  5,  5}, /* f3     -30 */
            {    60,     30,  50,  5,  5}, /* b1       0 */
            {    90,     45,  50,  5,  5}, /* b2       0 */
            {   150,     75,  50,  5,  5}, /* b3       0 */
            {   -30,      0, 100,  5,  5}, /* an       0 */
            { 50.75,   24.5,  50,  5,  5}, /* a1  -0.875 */
            {  45.5,     21,  50,  5,  5}, /* a2   -1.75 */
            {    35,   17.5,  50,  5,  5}, /* a3       0 */
            { 29.75,     14,  50,  5,  5}, /* a4  -0.875 */
            {   -30,    -15,  50,  5,  5}, /* a5       0 */
            {   -30,    -15,  50,  5,  5}, /* a6       0 */
            {   -30,    -15,  50,  5,  5}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    16,      8,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"IE", 2, 9, 6, 0x61, "a", "a", cnt | low | unr | vwl,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   790,    410,  50,  5,  5}, /* f1      15 */
            {   880,    470,  50,  5,  5}, /* f2      30 */
            {  2500,   1220,  50,  5,  5}, /* f3     -30 */
            {    60,     30,  50,  5,  5}, /* b1       0 */
            {    90,     45,  50,  5,  5}, /* b2       0 */
            {   150,     75,  50,  5,  5}, /* b3       0 */
            {   -30,      0, 100,  5,  5}, /* an       0 */
            { 50.75,   24.5,  50,  5,  5}, /* a1  -0.875 */
            {    49,   24.5,  50,  5,  5}, /* a2       0 */
            { 29.75,     14,  50,  5,  5}, /* a3  -0.875 */
            { 22.75,   10.5,  50,  5,  5}, /* a4  -0.875 */
            {   -30,    -15,  50,  5,  5}, /* a5       0 */
            {   -30,    -15,  50,  5,  5}, /* a6       0 */
            {   -30,    -15,  50,  5,  5}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    16,      8,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"OI", 2, 9, 6, 0x6F, "o", "o", bck | rnd | umd | vwl,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   490,    230,  50,  5,  5}, /* f1     -15 */
            {   820,    350,  50,  5,  5}, /* f2     -60 */
            {  2500,   1220,  50,  5,  5}, /* f3     -30 */
            {    60,     30,  50,  5,  5}, /* b1       0 */
            {    90,     45,  50,  5,  5}, /* b2       0 */
            {   150,     75,  50,  5,  5}, /* b3       0 */
            {   -30,      0, 100,  5,  5}, /* an       0 */
            { 50.75,   24.5,  50,  5,  5}, /* a1  -0.875 */
            {  45.5,     21,  50,  5,  5}, /* a2   -1.75 */
            { 22.75,   10.5,  50,  5,  5}, /* a3  -0.875 */
            {  17.5,      7,  50,  5,  5}, /* a4   -1.75 */
            {   -30,    -15,  50,  5,  5}, /* a5       0 */
            {   -30,    -15,  50,  5,  5}, /* a6       0 */
            {   -30,    -15,  50,  5,  5}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    16,      8,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"OU", 2, 9, 6, 0x61, "a", "a", cnt | low | unr | vwl,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   790,    410,  50,  5,  5}, /* f1      15 */
            {  1300,    590,  50,  5,  5}, /* f2     -60 */
            {  2500,   1220,  50,  5,  5}, /* f3     -30 */
            {    60,     30,  50,  5,  5}, /* b1       0 */
            {    90,     45,  50,  5,  5}, /* b2       0 */
            {   150,     75,  50,  5,  5}, /* b3       0 */
            {   -30,      0, 100,  5,  5}, /* an       0 */
            { 50.75,   24.5,  50,  5,  5}, /* a1  -0.875 */
            { 47.25,   24.5,  50,  5,  5}, /* a2   0.875 */
            {    35,   17.5,  50,  5,  5}, /* a3       0 */
            {    28,     14,  50,  5,  5}, /* a4       0 */
            {   -30,    -15,  50,  5,  5}, /* a5       0 */
            {   -30,    -15,  50,  5,  5}, /* a6       0 */
            {   -30,    -15,  50,  5,  5}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    16,      8,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"OV", 2, 8, 6, 0x55, "U", "U", bck | rnd | smh | vwl,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   370,    170,  50,  4,  4}, /* f1     -15 */
            {  1000,    470,  50,  4,  4}, /* f2     -30 */
            {  2500,   1220,  50,  4,  4}, /* f3     -30 */
            {    60,     30,  50,  4,  4}, /* b1       0 */
            {    90,     45,  50,  4,  4}, /* b2       0 */
            {   150,     75,  50,  4,  4}, /* b3       0 */
            {   -30,      0, 100,  4,  4}, /* an       0 */
            { 50.75,   24.5,  50,  4,  4}, /* a1  -0.875 */
            {    42,     21,  50,  4,  4}, /* a2       0 */
            {    28,     14,  50,  4,  4}, /* a3       0 */
            { 22.75,   10.5,  50,  4,  4}, /* a4  -0.875 */
            {   -30,    -15,  50,  4,  4}, /* a5       0 */
            {   -30,    -15,  50,  4,  4}, /* a6       0 */
            {   -30,    -15,  50,  4,  4}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    16,      8,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"OA", 2, 9, 6, 0xAB, "@", "@", cnt | mdl | unr | vwl,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   490,    230,  50,  5,  5}, /* f1     -15 */
            {  1480,    710,  50,  5,  5}, /* f2     -30 */
            {  2500,   1220,  50,  5,  5}, /* f3     -30 */
            {    60,     30,  50,  5,  5}, /* b1       0 */
            {    90,     45,  50,  5,  5}, /* b2       0 */
            {   150,     75,  50,  5,  5}, /* b3       0 */
            {   -30,      0, 100,  5,  5}, /* an       0 */
            { 50.75,   24.5,  50,  5,  5}, /* a1  -0.875 */
            { 50.75,   24.5,  50,  5,  5}, /* a2  -0.875 */
            { 33.25,   17.5,  50,  5,  5}, /* a3   0.875 */
            { 26.25,     14,  50,  5,  5}, /* a4   0.875 */
            {   -30,    -15,  50,  5,  5}, /* a5       0 */
            {   -30,    -15,  50,  5,  5}, /* a6       0 */
            {   -30,    -15,  50,  5,  5}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    16,      8,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"IA", 2, 9, 6, 0x49, "I", "I", fnt | smh | unr | vwl,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   310,    170,  50,  5,  5}, /* f1      15 */
            {  2200,   1070,  50,  5,  5}, /* f2     -30 */
            {  2920,   1460,  50,  5,  5}, /* f3       0 */
            {    60,     30,  50,  5,  5}, /* b1       0 */
            {    90,     45,  50,  5,  5}, /* b2       0 */
            {   150,     75,  50,  5,  5}, /* b3       0 */
            {   -30,      0, 100,  5,  5}, /* an       0 */
            { 50.75,   24.5,  50,  5,  5}, /* a1  -0.875 */
            {    35,   17.5,  50,  5,  5}, /* a2       0 */
            { 36.75,   17.5,  50,  5,  5}, /* a3  -0.875 */
            {  31.5,     14,  50,  5,  5}, /* a4   -1.75 */
            {   -30,    -15,  50,  5,  5}, /* a5       0 */
            {   -30,    -15,  50,  5,  5}, /* a6       0 */
            {   -30,    -15,  50,  5,  5}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    16,      8,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"IB", 2, 8, 6, 0x51, "@", "@", fnt | low | unr | vwl,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   490,    230,  50,  4,  4}, /* f1     -15 */
            {  1480,    710,  50,  4,  4}, /* f2     -30 */
            {  2500,   1220,  50,  4,  4}, /* f3     -30 */
            {    60,     30,  50,  4,  4}, /* b1       0 */
            {    90,     45,  50,  4,  4}, /* b2       0 */
            {   150,     75,  50,  4,  4}, /* b3       0 */
            {   -30,      0, 100,  4,  4}, /* an       0 */
            { 50.75,   24.5,  50,  4,  4}, /* a1  -0.875 */
            { 50.75,   24.5,  50,  4,  4}, /* a2  -0.875 */
            { 33.25,   17.5,  50,  4,  4}, /* a3   0.875 */
            { 26.25,     14,  50,  4,  4}, /* a4   0.875 */
            {   -30,    -15,  50,  4,  4}, /* a5       0 */
            {   -30,    -15,  50,  4,  4}, /* a6       0 */
            {   -30,    -15,  50,  4,  4}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    16,      8,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"AIR", 2, 9, 6, 0x45, "e", "E", fnt | lmd | unr | vwl,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   640,    350,  50,  5,  5}, /* f1      30 */
            {  2020,   1070,  50,  5,  5}, /* f2      60 */
            {  2500,   1220,  50,  5,  5}, /* f3     -30 */
            {    60,     30,  50,  5,  5}, /* b1       0 */
            {    90,     45,  50,  5,  5}, /* b2       0 */
            {   150,     75,  50,  5,  5}, /* b3       0 */
            {   -30,      0, 100,  5,  5}, /* an       0 */
            { 50.75,   24.5,  50,  5,  5}, /* a1  -0.875 */
            {    42,     21,  50,  5,  5}, /* a2       0 */
            {  38.5,   17.5,  50,  5,  5}, /* a3   -1.75 */
            {  31.5,     14,  50,  5,  5}, /* a4   -1.75 */
            {   -30,    -15,  50,  5,  5}, /* a5       0 */
            {   -30,    -15,  50,  5,  5}, /* a6       0 */
            {   -30,    -15,  50,  5,  5}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    16,      8,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"OOR", 2, 9, 6, 0x55, "U", "U", bck | rnd | smh | vwl,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   370,    170,  50,  5,  5}, /* f1     -15 */
            {  1000,    470,  50,  5,  5}, /* f2     -30 */
            {  2500,   1220,  50,  5,  5}, /* f3     -30 */
            {    60,     30,  50,  5,  5}, /* b1       0 */
            {    90,     45,  50,  5,  5}, /* b2       0 */
            {   150,     75,  50,  5,  5}, /* b3       0 */
            {   -30,      0, 100,  5,  5}, /* an       0 */
            { 50.75,   24.5,  50,  5,  5}, /* a1  -0.875 */
            {    42,     21,  50,  5,  5}, /* a2       0 */
            {    28,     14,  50,  5,  5}, /* a3       0 */
            { 22.75,      7,  50,  5,  5}, /* a4  -4.375 */
            {   -30,    -15,  50,  5,  5}, /* a5       0 */
            {   -30,    -15,  50,  5,  5}, /* a6       0 */
            {   -30,    -15,  50,  5,  5}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    16,      8,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    },

    {"OR", 2, 9, 6, 0x8D, "O" ,"O", bck | lmd | rnd | vwl,
        {
            {   270,    135,  50,  0,  0}, /* fn       0 */
            {   490,    230,  50,  5,  5}, /* f1     -15 */
            {   820,    470,  50,  5,  5}, /* f2      60 */
            {  2500,   1220,  50,  5,  5}, /* f3     -30 */
            {    60,     30,  50,  5,  5}, /* b1       0 */
            {    90,     45,  50,  5,  5}, /* b2       0 */
            {   150,     75,  50,  5,  5}, /* b3       0 */
            {   -30,      0, 100,  5,  5}, /* an       0 */
            { 50.75,   24.5,  50,  5,  5}, /* a1  -0.875 */
            {  45.5,     21,  50,  5,  5}, /* a2   -1.75 */
            { 22.75,   10.5,  50,  5,  5}, /* a3  -0.875 */
            {  17.5,      7,  50,  5,  5}, /* a4   -1.75 */
            {   -30,    -15,  50,  5,  5}, /* a5       0 */
            {   -30,    -15,  50,  5,  5}, /* a6       0 */
            {   -30,    -15,  50,  5,  5}, /* ab       0 */
            {    62,     31,  50,  0,  0}, /* av       0 */
            {    16,      8,  50,  0,  0}, /* avc      0 */
            {     0,      0,  50,  0,  0}, /* asp      0 */
            {     0,      0,  50,  0,  0}  /* af       0 */
        }
    } 
};

unsigned num_Elements = (sizeof(Elements) / sizeof(Elm_t));

// Forward function declarations.
unsigned phone_to_elm(char *phone, int n, darray_ptr elm);
unsigned holmes(unsigned nelm, unsigned char *elm, short *samp_base);
void *Darray_find(darray_t *a, unsigned n);
float resonator(resonator_ptr r, float input);

// Klatt synthesizer stuff...
klatt_global_t klatt_global;

/* Default values for the pars array */
klatt_frame_t def_pars =
{
    1330,  /* F0       long F0hz10;   */
      60,  /* AV       long AVdb;     */
     500,  /* F1       long F1hz;     */
      60,  /* BW1      long B1hz;     */
    1500,  /* F2       long F2hz;     */
      90,  /* BW2      long B2hz;     */
    2800,  /* F3       long F3hz;     */
     150,  /* BW3      long B3hz;     */
    3250,  /* F4       long F4hz;     */
     200,  /* BW4      long B4hz;     */
    3700,  /* F5       long F5hz;     */
     200,  /* BW5      long B5hz;     */
    4990,  /* F6       long F6hz;     */
     500,  /* BW6      long B6hz;     */
     270,  /* Fnz      long FNZhz;    */
     100,  /* BWnz     long BNZhz;    */
     270,  /* Fnp      long FNPhz;    */
     100,  /* BWnp     long BNPhz;    */
       0,  /* Aasp     long ASP;      */
      30,  /* Nopn     long Kopen;    */
       0,  /* Atur     long Aturb;    */
      10,  /* tilt     long TLTdb;    */
       0,  /* Afrc     long AF;       */
       0,  /* skew     long Kskew;    */
       0,  /* A1       long A1;       */
      80,  /* BWp1     long B1phz;    */
       0,  /* A2       long A2;       */
     200,  /* BWp2     long B2phz;    */
       0,  /* A3       long A3;       */
     350,  /* BWp3     long B3phz;    */
       0,  /* A4       long A4;       */
     500,  /* BWp4     long B4phz;    */
       0,  /* A5       long A5;       */
     600,  /* BWp5     long B5phz;    */
       0,  /* A6       long A6;       */
     800,  /* BWp6     long B6phz;    */
       0,  /* AN       long ANP;      */
       0,  /* AB       long AB;       */
       0,  /* AVpa     long AVpdb;    */
      62   /* G0       long Gain0;    */
};

// Want to keep around audio device specs.
struct this_type_doesnt_matter
{
    SDL_AudioSpec real;
//    SDL_AudioCVT cvt;
    int channel;
    bool bConverting;
} au_spec = { {0} };

// Initialize startup parameters for synthesizer and audio.
void tqsynth_init(int freq, uint16_t format, int channels, long base_F0)
{
    double mSec_per_frame = 10;

    klatt_global.samrate = 11025;   // Default sample rate is 11025 samples/sec.
                                    // This is about as fast as rsynth can work
                                    // without distortion.
    klatt_global.glsource = NATURAL;
    klatt_global.f0_flutter = 0;
    klatt_global.synthesis_model = ALL_PARALLEL;
    klatt_global.nspfr = (long) ((klatt_global.samrate * mSec_per_frame) / 1000);

    def_pars.F0hz10 = base_F0 ? base_F0 : 1330;
    def_pars.TLTdb = 10;

    au_spec.channel = -1;
    au_spec.real.freq = freq;
    au_spec.real.format = format;
    au_spec.real.channels = (uint8_t) channels;
	au_spec.bConverting = false;

    if (klatt_global.samrate != au_spec.real.freq || au_spec.real.channels != 1)
	{
        au_spec.bConverting = true;
	}

}

// Release a previously synthesized wave chunk.
void tqsynth_free_chunk(uint8_t *pu8Buf)
{
	MPO_FREE(pu8Buf);
}

// Take a synthesized sample and convert to an SDL-ready wave chunk.
bool audio_get_chunk(int num_samples, short *samples, sample_s *ptrSample)
{
	bool bResult = false;

    // Got something to work with, now do any conversion necessary to get
    // the wave into the spec the caller expects.
    unsigned int num_bytes = num_samples * sizeof(short);

	// if we need to do an audio conversion ...
    if (au_spec.bConverting)
    {
        SDL_AudioCVT cvt;

        // Need to do the wave conversion thing. The flite wave format
        // is always (as I understand it) 16-bit signed mono.
        if (1 == SDL_BuildAudioCVT(&cvt, AUDIO_S16, 1,
                                   klatt_global.samrate, au_spec.real.format,
                                   au_spec.real.channels, au_spec.real.freq))
        {
            cvt.buf = (uint8_t *) MPO_MALLOC(num_bytes * cvt.len_mult);
            cvt.len = num_bytes;
            memcpy(cvt.buf, (uint8_t *) samples, num_bytes);

			// if conversion succeeds
            if (0 == SDL_ConvertAudio(&cvt))
            {
				ptrSample->pu8Buf = cvt.buf;
				ptrSample->uLength = cvt.len_cvt;
				bResult = true;
            }
			else
			{
				printline("tqsynth.cpp ERROR : SDL_ConvertAudio failed");
				MPO_FREE(cvt.buf);
			}
        }
    }
    else
    {
		ptrSample->pu8Buf = (uint8_t *) MPO_MALLOC(num_bytes);

        // Sample wanted/real specs match, so don't need any conversion.
		if (NULL != ptrSample->pu8Buf)
		{
			memcpy(ptrSample->pu8Buf, (uint8_t *) samples, num_bytes);
			ptrSample->uLength = num_bytes;
			bResult = true;
		}
		else printline("tqsynth.cpp ERROR : MPO_MALLOC failed");
    }

    return bResult;
}

// Take a string of phonemes and synthesize to wave data.
bool tqsynth_phones_to_wave(char *phonemes, int len, sample_s *ptrSample)
{
    darray_t elm;
    unsigned frames;
	bool bResult = false;

    darray_init(&elm, sizeof(char), len);

    if ((frames = phone_to_elm(phonemes, len, &elm)))
    {
        unsigned max_samples = frames * klatt_global.nspfr;
        short *samp = (short *) malloc(sizeof(short) * max_samples);

        if (samp)
        {
            unsigned nsamp = holmes(elm.items,
                                    (unsigned char *) darray_find(&elm, 0),
                                    samp);

            bResult = audio_get_chunk(nsamp, samp, ptrSample);
            free(samp);
        }
		// else malloc failed ...
    }

    return bResult;
}

/* COUNTERS */
int time_count = 0;
long nper;                 /* Current loc in voicing period   40000 samp/s */

/* COUNTER LIMITS */
long T0;                   /* Fundamental period in output samples times 4 */
long nopen;                /* Number of samples in open phase of period  */
long nmod;                 /* Position in period to begin noise amp. modul */

/* Variables that have to stick around for awhile, and thus locals
   are not appropriate 
 */

/* Incoming parameter Variables which need to be updated synchronously  */
long F0hz10;               /* Voicing fund freq in Hz  */
long AVdb;                 /* Amp of voicing in dB,    0 to   70  */
long Kskew;                /* Skewness of alternate periods,0 to   40  */

/* Various amplitude variables used in main loop */
float amp_voice;           /* AVdb converted to linear gain  */
float amp_bypas;           /* AB converted to linear gain  */
float par_amp_voice;       /* AVpdb converted to linear gain  */
float amp_aspir;           /* AP converted to linear gain  */
float amp_frica;           /* AF converted to linear gain  */
float amp_breth;           /* ATURB converted to linear gain  */

/* State variables of sound sources */
long skew;                 /* Alternating jitter, in half-period units  */
float natglot_a;           /* Makes waveshape of glottal pulse when open  */
float natglot_b;           /* Makes waveshape of glottal pulse when open  */
float vwave;               /* Ditto, but before multiplication by AVdb  */
float vlast;               /* Previous output of voice  */
float nlast;               /* Previous output of random number generator  */
float glotlast;            /* Previous value of glotout  */
float decay;               /* TLTdb converted to exponential time const  */
float onemd;               /* in voicing one-pole low-pass filter  */
float minus_pi_t;          /* func. of sample rate */
float two_pi_t;            /* func. of sample rate */


/* INTERNAL MEMORY FOR DIGITAL RESONATORS AND ANTIRESONATOR  */
resonator_t rnpp, r1p, r2p, r3p, r4p, r5p, r6p,
            r1c, r2c, r3c, r4c, r5c, r6c, r7c, r8c,
            rnpc, rnz, rgl, rlp, rout;

/*
   function FLUTTER

   This function adds F0 flutter, as specified in:

   "Analysis, synthesis and perception of voice quality variations among
   female and male talkers" D.H. Klatt and L.C. Klatt JASA 87(2) February 1990.
   Flutter is added by applying a quasi-random element constructed from three
   slowly varying sine waves.
 */
void flutter(klatt_global_ptr globals, klatt_frame_ptr pars)
{
    long original_f0 = pars->F0hz10 / 10;
    double fla = (double) globals->f0_flutter / 50;
    double flb = (double) original_f0 / 100;
    double flc = sin(2 * PI * 12.7 * time_count);
    double fld = sin(2 * PI * 7.1 * time_count);
    double fle = sin(2 * PI * 4.7 * time_count);
    double delta_f0 = fla * flb * (flc + fld + fle) * 10;

    F0hz10 += (long) delta_f0;
}

float impulsive_source(long nper)
{
    static float doublet[] = {0., 13000000., -13000000.};

    if (nper < 3)
    {
        vwave = doublet[nper];
    }
    else
    {
        vwave = 0.0;
    }

    /* Low-pass filter the differenciated impulse with a critically-damped
        second-order filter, time constant proportional to Kopen */
    return resonator(&rgl, vwave);
}

/* Vwave is the differentiated glottal flow waveform, there is a weak
   spectral zero around 800 Hz, magic constants a,b reset pitch-synch
 */
float natural_source(long nper)
{
    float lgtemp;

    /* See if glottis open */
    if (nper < nopen)
    {
        natglot_a -= natglot_b;
        vwave += natglot_a;
        lgtemp = vwave * 0.028f;    /* function of samp_rate ? */
        return (lgtemp);
    }
    else
    {
        /* Glottis closed */
        vwave = 0.0;
        return (0.0);
    }
}

/*----------------------------------------------------------------------------*/
/* Convert formant freqencies and bandwidth into
   resonator difference equation coefficents
   f - Frequency of resonator in Hz
   bw - Bandwidth of resonator in Hz
   rp - Are output coefficients
 */
void setabc(long int f, long int bw, resonator_ptr rp)
{
    double arg = minus_pi_t * bw;
    float r = (float) exp(arg);      /* Let r  =  exp(-pi bw t) */

    rp->c = -(r * r);                /* Let c  =  -r**2 */
    arg = two_pi_t * f;
    rp->b = (float) (r * cos(arg) * 2.0);      /* Let b = r * 2*cos(2 pi f t) */
    rp->a = (float) (1.0 - rp->b - rp->c);    /* Let a = 1.0 - b - c */
}

/* Convienience function for setting parallel resonators with gain */
/* f - Frequency of resonator in Hz */
/* bw - Bandwidth of resonator in Hz */
/* rp - Are output coefficiants */
static void setabcg(long int f, long int bw, resonator_ptr rp, float gain)
{
    setabc(f, bw, rp);
    rp->a *= gain;
}

/* Convert formant freqencies and bandwidth into anti-resonator difference
   equation constants.

   f - Frequency of resonator in Hz
   bw - Bandwidth of resonator in Hz
   rp - Are output coefficiants
*/
void setzeroabc(long int f, long int bw, resonator_ptr rp)
{
    setabc(f, bw, rp);  /* First compute ordinary resonator coefficients */

    /* Now convert to antiresonator coefficients */
    rp->a = 1.0f / rp->a;   /* a'=  1/a */
    rp->b *= -rp->a;        /* b'= -b/a */
    rp->c *= -rp->a;        /* c'= -c/a */
}

/*----------------------------------------------------------------------------*/
/* Convert from decibels to a linear scale factor */
float DBtoLIN(long int dB)
{
    /*
    * Conversion table, db to linear, 87 dB --> 32767
    *                                 86 dB --> 29491 (1 dB down = 0.5**1/6)
    *                                 ...
    *                                 81 dB --> 16384 (6 dB down = 0.5)
    *                                 ...
    *                                  0 dB -->     0
    *
    * The just noticeable difference for a change in intensity of a vowel
    *   is approximately 1 dB.  Thus all amplitudes are quantized to 1 dB
    *   steps.
    */
    const float amptable[88] =
    {
        0.0, 0.0, 0.0, 0.0, 0.0,
        0.0, 0.0, 0.0, 0.0, 0.0,
        0.0, 0.0, 0.0, 6.0, 7.0,
        8.0, 9.0, 10.0, 11.0, 13.0,
        14.0, 16.0, 18.0, 20.0, 22.0,
        25.0, 28.0, 32.0, 35.0, 40.0,
        45.0, 51.0, 57.0, 64.0, 71.0,
        80.0, 90.0, 101.0, 114.0, 128.0,
        142.0, 159.0, 179.0, 202.0, 227.0,
        256.0, 284.0, 318.0, 359.0, 405.0,
        455.0, 512.0, 568.0, 638.0, 719.0,
        811.0, 911.0, 1024.0, 1137.0, 1276.0,
        1438.0, 1622.0, 1823.0, 2048.0, 2273.0,
        2552.0, 2875.0, 3244.0, 3645.0, 4096.0,
        4547.0, 5104.0, 5751.0, 6488.0, 7291.0,
        8192.0, 9093.0, 10207.0, 11502.0, 12976.0,
        14582.0, 16384.0, 18350.0, 20644.0, 23429.0,
        26214.0, 29491.0, 32767.0
    };

 /* Check limits or argument (can be removed in final product) */
    if (dB < 0)
        dB = 0;
    else if (dB >= 88)
        dB = 87;

    return amptable[dB] * 0.001f;
}

/* Reset selected parameters pitch-synchronously */
void pitch_synch_par_reset(klatt_global_ptr globals, klatt_frame_ptr frame, long ns)
{
    long temp;
    float temp1;
    /*
    * Constant natglot[] controls shape of glottal pulse as a function
    * of desired duration of open phase N0
    * (Note that N0 is specified in terms of 40,000 samples/sec of speech)
    *
    *    Assume voicing waveform V(t) has form: k1 t**2 - k2 t**3
    *
    *    If the radiation characterivative, a temporal derivative
    *      is folded in, and we go from continuous time to discrete
    *      integers n:  dV/dt = vwave[n]
    *                         = sum over i=1,2,...,n of { a - (i * b) }
    *                         = a n  -  b/2 n**2
    *
    *      where the  constants a and b control the detailed shape
    *      and amplitude of the voicing waveform over the open
    *      potion of the voicing cycle "nopen".
    *
    *    Let integral of dV/dt have no net dc flow --> a = (b * nopen) / 3
    *
    *    Let maximum of dUg(n)/dn be constant --> b = gain / (nopen * nopen)
    *      meaning as nopen gets bigger, V has bigger peak proportional to n
    *
    *    Thus, to generate the table below for 40 <= nopen <= 263:
    *
    *      natglot[nopen - 40] = 1920000 / (nopen * nopen)
    */
    const short natglot[224] =
    {
        1200, 1142, 1088, 1038, 991, 948, 907, 869, 833, 799,
        768, 738, 710, 683, 658, 634, 612, 590, 570, 551,
        533, 515, 499, 483, 468, 454, 440, 427, 415, 403,
        391, 380, 370, 360, 350, 341, 332, 323, 315, 307,
        300, 292, 285, 278, 272, 265, 259, 253, 247, 242,
        237, 231, 226, 221, 217, 212, 208, 204, 199, 195,
        192, 188, 184, 180, 177, 174, 170, 167, 164, 161,
        158, 155, 153, 150, 147, 145, 142, 140, 137, 135,
        133, 131, 128, 126, 124, 122, 120, 119, 117, 115,
        113, 111, 110, 108, 106, 105, 103, 102, 100, 99,
        97, 96, 95, 93, 92, 91, 90, 88, 87, 86,
        85, 84, 83, 82, 80, 79, 78, 77, 76, 75,
        75, 74, 73, 72, 71, 70, 69, 68, 68, 67,
        66, 65, 64, 64, 63, 62, 61, 61, 60, 59,
        59, 58, 57, 57, 56, 56, 55, 55, 54, 54,
        53, 53, 52, 52, 51, 51, 50, 50, 49, 49,
        48, 48, 47, 47, 46, 46, 45, 45, 44, 44,
        43, 43, 42, 42, 41, 41, 41, 41, 40, 40,
        39, 39, 38, 38, 38, 38, 37, 37, 36, 36,
        36, 36, 35, 35, 35, 35, 34, 34, 33, 33,
        33, 33, 32, 32, 32, 32, 31, 31, 31, 31,
        30, 30, 30, 30, 29, 29, 29, 29, 28, 28,
        28, 28, 27, 27
    };

    if (F0hz10 > 0)
    {
        T0 = (40 * globals->samrate) / F0hz10;

        /* Period in samp*4 */
        amp_voice = DBtoLIN(AVdb);

        /* Duration of period before amplitude modulation */
        nmod = T0;

        if (AVdb > 0)
        {
            nmod >>= 1;
        }

        /* Breathiness of voicing waveform */
        amp_breth = DBtoLIN(frame->Aturb) * 0.1f;

        /* Set open phase of glottal period */
        /* where  40 <= open phase <= 263 */
        nopen = 4 * frame->Kopen;

        if ((globals->glsource == IMPULSIVE) && (nopen > 263))
            nopen = 263;

        if (nopen >= (T0 - 1))
            nopen = T0 - 2;

        if (nopen < 40)
            nopen = 40;                  /* F0 max = 1000 Hz */

        /* Reset a & b, which determine shape of "natural" glottal waveform */
        natglot_b = natglot[nopen - 40];
        natglot_a = (natglot_b * nopen) * .333f;

        /* Reset width of "impulsive" glottal pulse */
        temp = globals->samrate / nopen;
        setabc(0L, temp, &rgl);

        /* Make gain at F1 about constant */
        temp1 = nopen * .00833f;
        rgl.a *= (temp1 * temp1);

        /* Truncate skewness so as not to exceed duration of closed phase
           of glottal period */
        temp = T0 - nopen;

        if (Kskew > temp)
            Kskew = temp;

        if (skew >= 0)
            skew = Kskew;   /* Reset skew to requested Kskew */
        else
            skew = -Kskew;

        /* Add skewness to closed portion of voicing period */
        T0 = T0 + skew;
        skew = -skew;
    }
    else
    {
        T0 = 4;            /* Default for f0 undefined */
        amp_voice = 0.0;
        nmod = T0;
        amp_breth = 0.0;
        natglot_a = 0.0;
        natglot_b = 0.0;
    }

    /* Reset these pars pitch synchronously or at update rate if f0=0 */
    if ((T0 != 4) || (ns == 0))
    {
        /* Set one-pole low-pass filter that tilts glottal source */
        decay = (0.033f * frame->TLTdb);	/* Function of samp_rate ? */

        if (decay > 0.0)
            onemd = 1.0f - decay;
        else
            onemd = 1.0;
    }
}

/* Get variable parameters from host computer,
   initially also get definition of fixed pars
 */
void frame_init(klatt_global_ptr globals, klatt_frame_ptr frame)
{
    long Gain0;         /* Overall gain, 60 dB is unity  0 to   60  */
    float amp_parF1;    /* A1 converted to linear gain  */
    float amp_parFN;    /* ANP converted to linear gain  */
    float amp_parF2;    /* A2 converted to linear gain  */
    float amp_parF3;    /* A3 converted to linear gain  */
    float amp_parF4;    /* A4 converted to linear gain  */
    float amp_parF5;    /* A5 converted to linear gain  */
    float amp_parF6;    /* A6 converted to linear gain  */

    /*
        Read speech frame definition into temp store
        and move some parameters into active use immediately
        (voice-excited ones are updated pitch synchronously
        to avoid waveform glitches).
    */
    F0hz10 = frame->F0hz10;
    AVdb = frame->AVdb - 7;

    if (AVdb < 0)
        AVdb = 0;

    amp_aspir = DBtoLIN(frame->ASP) * .05f;
    amp_frica = DBtoLIN(frame->AF) * 0.25f;

    Kskew = frame->Kskew;
    par_amp_voice = DBtoLIN(frame->AVpdb);

    /* Fudge factors (which comprehend affects of formants on each other?)
        with these in place ALL_PARALLEL should sound as close as 
        possible to CASCADE_PARALLEL.
        Possible problem feeding in Holmes's amplitudes given this.
    */
    amp_parF1 = DBtoLIN(frame->A1) * 0.4f;	/* -7.96 dB */
    amp_parF2 = DBtoLIN(frame->A2) * 0.15f;	/* -16.5 dB */
    amp_parF3 = DBtoLIN(frame->A3) * 0.06f;	/* -24.4 dB */
    amp_parF4 = DBtoLIN(frame->A4) * 0.04f;	/* -28.0 dB */
    amp_parF5 = DBtoLIN(frame->A5) * 0.022f;	/* -33.2 dB */
    amp_parF6 = DBtoLIN(frame->A6) * 0.03f;	/* -30.5 dB */
    amp_parFN = DBtoLIN(frame->ANP) * 0.6f;	/* -4.44 dB */
    amp_bypas = DBtoLIN(frame->AB) * 0.05f;	/* -26.0 db */

    if (globals->nfcascade >= 8)
    {
        /* Inside Nyquist rate ? */
        if (globals->samrate >= 16000)
            setabc(7500, 600, &r8c);
        else
            globals->nfcascade = 6;
    }

    if (globals->nfcascade >= 7)
    {
        /* Inside Nyquist rate ? */
        if (globals->samrate >= 16000)
            setabc(6500, 500, &r7c);
        else
            globals->nfcascade = 6;
    }

    /* Set coefficients of variable cascade resonators */
    if (globals->nfcascade >= 6)
        setabc(frame->F6hz, frame->B6hz, &r6c);

    if (globals->nfcascade >= 5)
        setabc(frame->F5hz, frame->B5hz, &r5c);

    setabc(frame->F4hz, frame->B4hz, &r4c);
    setabc(frame->F3hz, frame->B3hz, &r3c);
    setabc(frame->F2hz, frame->B2hz, &r2c);
    setabc(frame->F1hz, frame->B1hz, &r1c);

    /* Set coeficients of nasal resonator and zero antiresonator */
    setabc(frame->FNPhz, frame->BNPhz, &rnpc);
    setzeroabc(frame->FNZhz, frame->BNZhz, &rnz);

    /* Set coefficients of parallel resonators, and amplitude of outputs */
    setabcg(frame->F1hz, frame->B1phz, &r1p, amp_parF1);
    setabcg(frame->FNPhz, frame->BNPhz, &rnpp, amp_parFN);
    setabcg(frame->F2hz, frame->B2phz, &r2p, amp_parF2);
    setabcg(frame->F3hz, frame->B3phz, &r3p, amp_parF3);
    setabcg(frame->F4hz, frame->B4phz, &r4p, amp_parF4);
    setabcg(frame->F5hz, frame->B5phz, &r5p, amp_parF5);
    setabcg(frame->F6hz, frame->B6phz, &r6p, amp_parF6);

    /* fold overall gain into output resonator */
    Gain0 = frame->Gain0 - 3;

    if (Gain0 <= 0)
        Gain0 = 57;

    /* output low-pass filter - resonator with freq 0 and BW = globals->samrate
        Thus 3db point is globals->samrate/2 i.e. Nyquist limit.
        Only 3db down seems rather mild...
    */
    setabcg(0L, (long) globals->samrate, &rout, DBtoLIN(Gain0));
}

short clip(float input)
{
    long temp = (long) input;

    /* clip on boundaries of 16-bit word */
    if (temp < -32767)
        temp = -32767;
    else if (temp > 32767)
        temp = 32767;

    return (short) temp;
}

/* Generic resonator function */
float resonator(resonator_ptr r, float input)
{
    register float x = r->a * input + r->b * r->p1 + r->c * r->p2;

    r->p2 = r->p1;
    r->p1 = x;

    return x;
}

/*
   Generic anti-resonator function
   Same as resonator except that a,b,c need to be set with setzeroabc()
   and we save inputs in p1/p2 rather than outputs.
   There is currently only one of these - "rnz"

   Output = (rnz.a * input) + (rnz.b * oldin1) + (rnz.c * oldin2)
*/
float antiresonator(resonator_ptr r, float input)
{
    register float x = r->a * input + r->b * r->p1 + r->c * r->p2;

    r->p2 = r->p1;
    r->p1 = input;

    return x;
}

/*
   function PARWAV

   CONVERT FRAME OF PARAMETER DATA TO A WAVEFORM CHUNK
   Synthesize globals->nspfr samples of waveform and store in wave_data[].
 */

void parwave(klatt_global_ptr globals, klatt_frame_ptr frame, short int *wave_data)
{
    long ns;
    float out = 0.0;
    /* Output of cascade branch, also final output  */

    /* Initialize synthesizer and get specification for current speech
       frame from host microcomputer */

    frame_init(globals, frame);

    if (globals->f0_flutter != 0)
    {
        time_count++;                  /* used for f0 flutter */
        flutter(globals, frame);       /* add f0 flutter */
    }

    /* MAIN LOOP, for each output sample of current frame: */

    for (ns = 0; ns < globals->nspfr; ns++)
    {
        static unsigned long seed = 5; /* Fixed staring value */
        float noise;
        int n4;
        float sourc;       /* Sound source if all-parallel config used  */
        float glotout;     /* Output of glottal sound source  */
        float par_glotout; /* Output of parallelglottal sound sourc  */
        float voice;       /* Current sample of voicing waveform  */
        float frics;       /* Frication sound source  */
        float aspiration;  /* Aspiration sound source  */
        long nrand;        /* Varible used by random number generator  */

        /* Our own code like rand(), but portable
            whole upper 31 bits of seed random 
            assumes 32-bit unsigned arithmetic
            with untested code to handle larger.
            */
        seed = seed * 1664525 + 1;

        if (8 * sizeof(unsigned long) > 32)
            seed &= 0xFFFFFFFF;

        /* Shift top bits of seed up to top of long then back down to LS 14 bits */
        /* Assumes 8 bits per sizeof unit i.e. a "byte" */
        nrand = (((long) seed) << (8 * sizeof(long) - 32)) >> (8 * sizeof(long) - 14);

        /* Tilt down noise spectrum by soft low-pass filter having
            *    a pole near the origin in the z-plane, i.e.
            *    output = input + (0.75 * lastoutput) */
        noise = nrand + (0.75f * nlast);	/* Function of samp_rate ? */
        nlast = noise;

        /* Amplitude modulate noise (reduce noise amplitude during
            second half of glottal period) if voicing simultaneously present
            */
        if (nper > nmod)
            noise *= 0.5;

        /* Compute frication noise */
        sourc = frics = amp_frica * noise;

        /* Compute voicing waveform : (run glottal source simulation at
           4 times normal sample rate to minimize quantization noise in 
           period of female voice) */
        for (n4 = 0; n4 < 4; n4++)
        {
            if (globals->glsource == IMPULSIVE)
            {
                /* Use impulsive glottal source */
                voice = impulsive_source(nper);
            }
            else
            {
                /* Or use a more-natural-shaped source waveform with excitation
                   occurring both upon opening and upon closure, stronest at
                   closure */
                voice = natural_source(nper);
            }

            /* Reset period when counter 'nper' reaches T0 */
            if (nper >= T0)
            {
                nper = 0;
                pitch_synch_par_reset(globals, frame, ns);
            }

            /* Low-pass filter voicing waveform before downsampling from 4*globals->samrate */
            /* to globals->samrate samples/sec.  Resonator f=.09*globals->samrate, bw=.06*globals->samrate  */
            voice = resonator(&rlp, voice);	/* in=voice, out=voice */

            /* Increment counter that keeps track of 4*globals->samrate samples/sec */
            nper++;
        }

        /* Tilt spectrum of voicing source down by soft low-pass filtering, amount
           of tilt determined by TLTdb */
        voice = (voice * onemd) + (vlast * decay);
        vlast = voice;

        /* Add breathiness during glottal open phase */
        if (nper < nopen)
        {
            /* Amount of breathiness determined by parameter Aturb */
            /* Use nrand rather than noise because noise is low-passed */
            voice += amp_breth * nrand;
        }

        /* Set amplitude of voicing */
        glotout = amp_voice * voice;

        /* Compute aspiration amplitude and add to voicing source */
        aspiration = amp_aspir * noise;
        glotout += aspiration;

        par_glotout = glotout;

        if (globals->synthesis_model != ALL_PARALLEL)
        {
            /* Cascade vocal tract, excited by laryngeal sources.
               Nasal antiresonator, then formants FNP, F5, F4, F3, F2, F1  */
            float rnzout = antiresonator(&rnz, glotout);	/* Output of cascade nazal zero resonator  */
            float casc_next_in = resonator(&rnpc, rnzout);	/* in=rnzout, out=rnpc.p1 */

            /* Recoded from sequence of if's to use C's fall through switch
               semantics. May allow compiler to optimize. */
            switch (globals->nfcascade)
            {
                case 8:
                    /* Do not use unless samrat = 16000 */
                    casc_next_in = resonator(&r8c, casc_next_in);
                case 7:
                    /* Do not use unless samrat = 16000 */
                    casc_next_in = resonator(&r7c, casc_next_in);
                case 6:
                    /* Do not use unless long vocal tract or samrat increased */
                    casc_next_in = resonator(&r6c, casc_next_in);
                case 5:
                    casc_next_in = resonator(&r5c, casc_next_in);
                case 4:
                    casc_next_in = resonator(&r4c, casc_next_in);
                case 3:
                    casc_next_in = resonator(&r3c, casc_next_in);
                case 2:
                    casc_next_in = resonator(&r2c, casc_next_in);
                case 1:
                    out = resonator(&r1c, casc_next_in);
                    break;
                default:
                    out = 0.0;
            }
        }
        else
        {
            /* Is ALL_PARALLEL */
            /* NIS - rsynth "hack"
               As Holmes' scheme is weak at nasals and (physically) nasal cavity
               is "back near glottis" feed glottal source through nasal resonators
               Don't think this is quite right, but improves things a bit */
            par_glotout = antiresonator(&rnz, par_glotout);
            par_glotout = resonator(&rnpc, par_glotout);

            /* And just use r1p NOT rnpp */
            out = resonator(&r1p, par_glotout);

            /* Sound sourc for other parallel resonators is frication
               plus first difference of voicing waveform. */
            sourc += (par_glotout - glotlast);
            glotlast = par_glotout;
        }

        /* Standard parallel vocal tract
           Formants F6, F5, F4, F3, F2, outputs added with alternating sign */
        out = resonator(&r6p, sourc) - out;
        out = resonator(&r5p, sourc) - out;
        out = resonator(&r4p, sourc) - out;
        out = resonator(&r3p, sourc) - out;
        out = resonator(&r2p, sourc) - out;

        out = amp_bypas * sourc - out;

        out = resonator(&rout, out);

        /* Convert back to integer */
        *wave_data++ = clip(out);
    }
}

void parwave_init(klatt_global_ptr globals)
{
    long FLPhz = (950 * globals->samrate) / 10000;
    long BLPhz = (630 * globals->samrate) / 10000;

    minus_pi_t = (float) (-PI / globals->samrate);
    two_pi_t = -2.0f * minus_pi_t;

    setabc(FLPhz, BLPhz, &rlp);
    nper = 0;      /* LG */
    T0 = 0;        /* LG */

    rnpp.p1 = 0;   /* parallel nasal pole  */
    rnpp.p2 = 0;

    r1p.p1 = 0;    /* parallel 1st formant */
    r1p.p2 = 0;

    r2p.p1 = 0;    /* parallel 2nd formant */
    r2p.p2 = 0;

    r3p.p1 = 0;    /* parallel 3rd formant */
    r3p.p2 = 0;

    r4p.p1 = 0;    /* parallel 4th formant */
    r4p.p2 = 0;

    r5p.p1 = 0;    /* parallel 5th formant */
    r5p.p2 = 0;

    r6p.p1 = 0;    /* parallel 6th formant */
    r6p.p2 = 0;

    r1c.p1 = 0;    /* cascade 1st formant  */
    r1c.p2 = 0;

    r2c.p1 = 0;    /* cascade 2nd formant  */
    r2c.p2 = 0;

    r3c.p1 = 0;    /* cascade 3rd formant  */
    r3c.p2 = 0;

    r4c.p1 = 0;    /* cascade 4th formant  */
    r4c.p2 = 0;

    r5c.p1 = 0;    /* cascade 5th formant  */
    r5c.p2 = 0;

    r6c.p1 = 0;    /* cascade 6th formant  */
    r6c.p2 = 0;

    r7c.p1 = 0;
    r7c.p2 = 0;

    r8c.p1 = 0;
    r8c.p2 = 0;

    rnpc.p1 = 0;   /* cascade nasal pole  */
    rnpc.p2 = 0;

    rnz.p1 = 0;    /* cascade nasal zero  */
    rnz.p2 = 0;

    rgl.p1 = 0;    /* crit-damped glot low-pass filter */
    rgl.p2 = 0;

    rlp.p1 = 0;    /* downsamp low-pass filter  */
    rlp.p2 = 0;

    vlast = 0;     /* Previous output of voice  */
    nlast = 0;     /* Previous output of random number generator  */
    glotlast = 0;  /* Previous value of glotout  */
}

float filter(filter_ptr p, float v)
{
    return p->v = (p->a * v + p->b * p->v);
}

/* 'a' is dominant element, 'b' is dominated
   ext is flag to say to use external times from 'a' rather
   than internal i.e. ext != 0 if 'a' is NOT current element.
 */
void set_trans(slope_t *t, Elm_ptr a, Elm_ptr b, int ext)
{
    int i;

    for (i = 0; i < nEparm; i++)
    {
        t[i].t = ((ext) ? a->p[i].ed : a->p[i].id) * SPEED;

        if (t[i].t)
            t[i].v = a->p[i].fixd + (a->p[i].prop * b->p[i].stdy) * (float) 0.01;
        else
            t[i].v = b->p[i].stdy;
    }
}

/*              
   ______________ b
   /
   /
   /
   a____________/                 
   0   d
   ---------------t---------------
 */
float linear(float a, float b, int t, int d)
{
    if (t <= 0)
        return a;
    else if (t >= d)
        return b;
    else
    {
        float f = (float) t / (float) d;
        return a + (b - a) * f;
    }
}

float interpolate(slope_t *s, slope_t *e, float mid, int t, int d)
{
    float steady = (float) d - (s->t + e->t);

    if (steady >= 0)
    {
        /* Value reaches stready state somewhere ... */
        if (t < s->t)
            return linear(s->v, mid, t, s->t);	/* initial transition */
        else
        {
            t -= s->t;

            if (t <= steady)
                return mid; /* steady state */
            else
                return linear(mid, e->v, (int) (t - steady), e->t);
                /* final transition */
        }
    }
    else
    {
        float f = (float) 1.0 - ((float) t / (float) d);
        float sp = linear(s->v, mid, t, s->t);
        float ep = linear(e->v, mid, d - t, e->t);

        return f * sp + ((float) 1.0 - f) * ep;
    }
}

unsigned holmes(unsigned nelm, unsigned char *elm, short *samp_base)
{
    filter_t flt[nEparm];
    klatt_frame_t pars;
    short *samp = samp_base;
    Elm_ptr le = &Elements[0];
    unsigned i = 0;
    unsigned tstress = 0;
    unsigned ntstress = 0;
    slope_t stress_s;
    slope_t stress_e;
    float top = 1.1f * def_pars.F0hz10;
    int j;

    pars = def_pars;
    pars.FNPhz = (long) le->p[fn].stdy;
    pars.B1phz = pars.B1hz = 60;
    pars.B2phz = pars.B2hz = 90;
    pars.B3phz = pars.B3hz = 150;
    pars.B4phz = def_pars.B4phz;

    /* flag new utterance */
    parwave_init(&klatt_global);

    /* Set stress attack/decay slope */
    stress_s.t = 40;
    stress_e.t = 40;
    stress_e.v = 0.0;

    for (j = 0; j < nEparm; j++)
    {
        flt[j].v = le->p[j].stdy;
        flt[j].a = 1.0f;
        flt[j].b = 0;
    }

    while (i < nelm)
    {
        Elm_ptr ce = &Elements[elm[i++]];
        unsigned dur = elm[i++];
        i++; /* skip stress */

        /* Skip zero length elements which are only there to affect
           boundary values of adjacent elements. */
        if (dur > 0)
        {
            Elm_ptr ne = (i < nelm) ? &Elements[elm[i]] : &Elements[0];
            slope_t start[nEparm];
            slope_t end[nEparm];
            unsigned t;

            if (ce->rk > le->rk)
            {
                set_trans(start, ce, le, 0);
                /* we dominate last */
            }
            else
            {
                set_trans(start, le, ce, 1);
                /* last dominates us */
            }

            if (ne->rk > ce->rk)
            {
                set_trans(end, ne, ce, 1);
                /* next dominates us */
            }
            else
            {
                set_trans(end, ce, ne, 0);
                /* we dominate next */
            }

            for (t = 0; t < dur; t++, tstress++)
            {
                float base = top * 0.8f /* 3 * top / 5 */;
                float tp[nEparm];
                int j;

                if (tstress == ntstress)
                {
                    unsigned j = i;
                    stress_s = stress_e;
                    tstress = 0;
                    ntstress = dur;

                    while (j <= nelm)
                    {
                        Elm_ptr e   = (j < nelm) ? &Elements[elm[j++]] : &Elements[0];
                        unsigned du = (j < nelm) ? elm[j++] : 0;
                        unsigned s  = (j < nelm) ? elm[j++] : 3;

                        if (s || e->feat & vwl)
                        {
                            unsigned d = 0;

                            if (s)
                                stress_e.v = (float) s / 3;
                            else
                                stress_e.v = (float) 0.1;

                            do
                            {
                                d += du;
                                e = (j < nelm) ? &Elements[elm[j++]] : &Elements[0];
                                du = elm[j++];
                            } while ((e->feat & vwl) && elm[j++] == s);

                            ntstress += d / 2;
                            break;
                        }

                        ntstress += du;
                    }
                }

                for (j = 0; j < nEparm; j++)
                {
                    tp[j] = filter(flt + j,
                                   interpolate(&start[j], &end[j],
                                               (float) ce->p[j].stdy, t, dur));
                }

                /* Now call the synth for each frame */
                pars.F0hz10 = (long) (base + (top - base) * interpolate(&stress_s, &stress_e, (float) 0, tstress, ntstress));

                pars.AVdb = pars.AVpdb = (long) tp[av];
                pars.AF = (long) tp[af];
                pars.FNZhz = (long) tp[fn];
                pars.ASP = (long) tp[asp];
                pars.Aturb = (long) tp[avc];
                pars.B1phz = pars.B1hz = (long) tp[b1];
                pars.B2phz = pars.B2hz = (long) tp[b2];
                pars.B3phz = pars.B3hz = (long) tp[b3];
                pars.F1hz = (long) tp[f1];
                pars.F2hz = (long) tp[f2];
                pars.F3hz = (long) tp[f3];

#define AMP_ADJ 20
                // AMP_ADJ + is a bodge to get amplitudes up to klatt-compatible
                // levels. Needs to be fixed properly in tables.
                pars.AB = AMP_ADJ + (long) tp[ab];
                pars.A5 = AMP_ADJ + (long) tp[a5];
                pars.A6 = AMP_ADJ + (long) tp[a6];
                pars.A1 = AMP_ADJ + (long) tp[a1];
                pars.A2 = AMP_ADJ + (long) tp[a2];
                pars.A3 = AMP_ADJ + (long) tp[a3];
                pars.A4 = AMP_ADJ + (long) tp[a4];

                parwave(&klatt_global, &pars, samp);
                samp += klatt_global.nspfr;
            }
        }

        le = ce;
    }

    return (samp - samp_base);
}

trie_ptr phtoelm = NULL;

Elm_ptr find_elm(char *s)
{
    Elm_ptr e = Elements;

    while (e < Elements + num_Elements)
    {
        if (! strcmp(s, e->name))
            return e;

        e++;
    }

    return NULL;
}

void trie_insert(trie_ptr *r, const char *s, void *value)
{
    trie_ptr p = NULL;
    char ch;

    while ((ch = *s++))
    {
        while ((p = *r))
        {
            if (p->ch == ch)
                break;
            else
                r = &p->otherwise;
        }

        if (! p)
        {
            p = (trie_ptr) malloc(sizeof(*p));
            memset(p, 0, sizeof(*p));
            p->ch = ch;
            *r = p;
        }

        r = &p->more;
    }

    p->value = value;
}

char *trie_lookup(trie_ptr *r, char **sp)
{
    char *s = *sp;
    char *value = NULL;
    char ch;

    while ((ch = *s))
    {
        trie_ptr *l = r;
        trie_ptr p;

        while ((p = *l))
        {
            if (p->ch == ch)
                break;
            else
                l = &p->otherwise;
        }

        if (p)
        {
            *l = p->otherwise;
            p->otherwise = *r;
            *r = p;
            r = &p->more;
            value = (char *) p->value;
            s++;
        }
        else
            break;
    }

    *sp = s;

    return value;
}

void enter(const char *p, ...)
{
    va_list ap;
    char *s;
    char buf[20];
    char *x = buf + 1;

    va_start(ap, p);

    while ((s = va_arg(ap, char *)))
    {
        Elm_ptr e = find_elm(s);

        if (e)
            *x++ = (char) (e - Elements);
        else
        {
            char msg[80];

            sprintf(msg, "tqsynth: Cannot find element %s", s);
       		printline(msg);
        }
    }

    va_end(ap);

    buf[0] = (char) (x - buf) - 1;
    x = (char *) malloc(buf[0] + 1);
    memcpy(x, buf, buf[0] + 1);
    trie_insert(&phtoelm, p, x);
}

void enter_phonemes(void)
{
    enter(" ", "Q", NULL);
    enter("p", "P", "PY", "PZ", NULL);
    enter("t", "T", "TY", "TZ", NULL);
    enter("k", "K", "KY", "KZ", NULL);
    enter("b", "B", "BY", "BZ", NULL);
    enter("d", "D", "DY", "DZ", NULL);
    enter("g", "G", "GY", "GZ", NULL);
    enter("m", "M", NULL);
    enter("n", "N", NULL);
    enter("N", "NG", NULL);
    enter("f", "F", NULL);
    enter("T", "TH", NULL);
    enter("s", "S", NULL);
    enter("S", "SH", NULL);
    enter("h", "H", NULL);
    enter("v", "V", "QQ", "V", NULL);
    enter("D", "DH", "QQ", "DI", NULL);
    enter("z", "Z", "QQ", "ZZ", NULL);
    enter("Z", "ZH", "QQ", "ZH", NULL);
    enter("tS", "CH", "CI", NULL);
    enter("dZ", "J", "JY", "QQ", "JY", NULL);
    enter("l", "L", NULL);
    enter("r", "R", NULL);
    enter("rr", "R", "QQ", "R", NULL);
    enter("R", "RX", NULL);
    enter("w", "W", NULL);
    enter("x", "X", NULL); 
    enter("%", "QQ", NULL); /* stop-ness - not quite glottal stop */
    enter("j", "Y", NULL);
    enter("I", "I", NULL);
    enter("e", "E", NULL);
    enter("&", "AA", NULL);
    enter("V", "U", NULL);
    enter("0", "O", NULL);
    enter("U", "OO", NULL);
    enter("@", "A", NULL);
    enter("i", "EE", NULL);
    enter("3", "ER", NULL);
    enter("A", "AR", NULL);
    enter("O", "AW", NULL);
    enter("u", "UU", NULL);
    enter("o", "OI", NULL);
    enter("eI", "AI", "I", NULL);
    enter("aI", "IE", "I", NULL);
    enter("oI", "OI", "I", NULL);
    enter("aU", "OU", "OV", NULL);
    enter("@U", "OA", "OV", NULL);
    enter("I@", "IA", "IB", NULL);
    enter("e@", "AIR", "IB", NULL);
    enter("U@", "OOR", "IB", NULL);
    enter("O@", "OR", "IB", NULL);
    enter("oU", "OI", "OV", NULL);
}

int phone_append(darray_ptr p, int ch)
{
    char *s = (char *) darray_find(p, p->items);

    *s = (char) ch;

    return ch;
}

unsigned phone_to_elm(char *phone, int n, darray_ptr elm)
{
    int stress = 0;
    char *s = phone;
    unsigned t = 0;
    char *limit = s + n;

    if (! phtoelm)
        enter_phonemes();

    while (s < limit && *s)
    {
        char *e = trie_lookup(&phtoelm, &s);

        if (e)
        {
            int n = *e++;

            while (n-- > 0)
            {
                int x = *e++;

                Elm_ptr p = &Elements[x];

                // This works because only vowels have ud != du,
                // and we set stress just before a vowel
                phone_append(elm, x);
                t += phone_append(elm, (p->du + p->ud) / 2 * SPEED);
                phone_append(elm, stress);
            }
        }
        else
        {
            char msg[80];
            char ch = *s++;

            switch (ch)
            {
                case '\'':                /* Primary stress */
                    stress = 3;
                    break;
                case ',':                 /* Secondary stress */
                    stress = 2;
                    break;
                case '+':                 /* Tertiary stress */
                    stress = 1;
                    break;
                case '-':                 /* hyphen in input */
                    break;
                default:
                    sprintf(msg, "tqsynth: Ignoring %c in '%.*s'", ch, n, phone);
                    printline(msg);
                    break;
            }
        }
    }

    return t;
}

// Return pointer to nth item.
void *Darray_find(darray_t *a, unsigned n)
{
    if (n >= a->alloc || n >= a->items)
    {
        unsigned osize = a->items * a->esize;
        unsigned nsize;

        if (!a->esize)
            abort();

        if (n >= a->alloc)
        {
            unsigned add = (a->get) ? a->get : 1;
            char *ndata = (char *) malloc(nsize = (n + add) * a->esize);

            if (ndata)
            {
                if (osize)
                    memcpy(ndata, a->data, osize);

                if (a->data)
                    free(a->data);

                a->data = ndata;
                a->alloc = n + add;
            }
            else
                return NULL;
        }
        else
            nsize = (n + 1) * a->esize;

        if (n >= a->items)
        {
            memset(a->data + osize, 0, nsize - osize);
            a->items = n + 1;
        }
    }

    return (void *) (a->data + n * a->esize);
}

// Delete nth item.
int darray_delete(darray_t *a, unsigned n)
{
    char *p = (char *) darray_find(a, n);

    if (p)
    {
        if (a->items)
        {
            a->items--;

            while (n++ < a->items)
            {
                memcpy(p, p + a->esize, a->esize);
                p += a->esize;
            }

            memset(p, 0, a->esize);

            return 1;
        }
        else
            abort();
    }
    else
        return 0;
}

// Free the entire array.
void darray_free(darray_t *a)
{
    if (a->data)
    {
        free(a->data);
        a->data = NULL;
    }

    a->items = a->alloc = 0;
}
